mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-30 10:52:50 +00:00
Remove files that we don't use and are unlikely to use. You can
still get them with "cvs upd -r pam_unpruned" if you want to look at them.
This commit is contained in:
parent
46d4978e39
commit
9748c8ad8f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41336
@ -1,39 +0,0 @@
|
||||
##
|
||||
# $Id: README,v 1.6 1997/02/15 19:21:08 morgan Exp $
|
||||
##
|
||||
# $Log: README,v $
|
||||
# Revision 1.6 1997/02/15 19:21:08 morgan
|
||||
# fixed email
|
||||
#
|
||||
# Revision 1.5 1996/08/09 05:29:43 morgan
|
||||
# trimmed in line with the removal of applications from the distribution
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
(now we are getting networked apps, be careful to try and test on a
|
||||
securely isolated system!)
|
||||
|
||||
N=2 <-- blank xsh
|
||||
|
||||
Following a 'make install' (which should be done as root) in the
|
||||
parent directory this directory will contain $N binaries. The source
|
||||
for these programs is in ../examples. They are various short programs
|
||||
to use and otherwise test-drive the Linux-PAM libraries/modules with.
|
||||
|
||||
These programs grant no privileges, but they give an idea of how well
|
||||
the modules are working.
|
||||
|
||||
blank is new as of Linux-PAM-0.21. If you are writing/modifying an
|
||||
application it might be a place to start...
|
||||
|
||||
xsh is new as of Linux-PAM-0.31, it is identical to blank, but invokes
|
||||
/bin/sh if the user is authenticated.
|
||||
|
||||
[other apps are to be found in SimplePAMApps and many more on Red
|
||||
Hat's server.. http://www.redhat.com/]
|
||||
|
||||
Best wishes
|
||||
|
||||
Andrew
|
||||
(morgan@parc.power.net)
|
@ -1,60 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.8 1997/04/05 06:59:33 morgan Exp $
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.8 1997/04/05 06:59:33 morgan
|
||||
# fakeroot and $(MAKE)
|
||||
#
|
||||
# Revision 1.7 1997/02/15 15:53:51 morgan
|
||||
# added lines to make pam_conv1
|
||||
#
|
||||
# Revision 1.6 1996/11/10 19:48:09 morgan
|
||||
# fix for systems that have not installed bash in /bin/
|
||||
#
|
||||
# Revision 1.5 1996/03/16 22:21:26 morgan
|
||||
# added 'make remove' option
|
||||
#
|
||||
# Revision 1.4 1996/03/10 21:01:47 morgan
|
||||
# added .ignore_age flag file
|
||||
#
|
||||
# Revision 1.3 1996/03/10 17:41:28 morgan
|
||||
# make RCScheck check for the presence of the executable before running
|
||||
# it!
|
||||
#
|
||||
# Revision 1.2 1996/03/10 17:16:42 morgan
|
||||
# added md5RCS/ RCScheck entry
|
||||
#
|
||||
#
|
||||
|
||||
dummy:
|
||||
@echo "*** This is not a top level Makefile!"
|
||||
|
||||
##########################################################
|
||||
|
||||
all:
|
||||
$(MAKE) -C pam_conv1 all
|
||||
|
||||
install: $(FAKEROOT)$(CONFIGED)/pam.conf
|
||||
$(MAKE) -C pam_conv1 install
|
||||
|
||||
$(FAKEROOT)$(CONFIGED)/pam.conf: ./pam.conf
|
||||
bash -f ./install_conf
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(CONFIGED)/pam.conf
|
||||
$(MAKE) -C pam_conv1 remove
|
||||
|
||||
check:
|
||||
bash -f ./md5itall
|
||||
|
||||
RCScheck:
|
||||
if [ -x ./md5RCS ]; then bash -f ./md5RCS ; fi
|
||||
|
||||
lclean:
|
||||
rm -f core *~ .ignore_age
|
||||
|
||||
clean: lclean
|
||||
$(MAKE) -C pam_conv1 clean
|
||||
|
||||
extraclean: lclean
|
||||
$(MAKE) -C pam_conv1 extraclean
|
@ -1,178 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# [This file was lifted from an X distribution. There was no explicit
|
||||
# copyright in the file, but the following text was associated with it.
|
||||
# should anyone from the X Consortium wish to alter the following
|
||||
# text. Please email <morgan@parc.power.net> Thanks. ]
|
||||
#
|
||||
# --------------------------
|
||||
# The X Consortium maintains and distributes the X Window System and
|
||||
# related software and documentation in coordinated releases. A release
|
||||
# consists of two distinct parts:
|
||||
#
|
||||
# 1) Specifications and Sample implementations of X Consortium
|
||||
# standards, and
|
||||
#
|
||||
# 2) software and documentation contributed by the general X Consortium
|
||||
# community.
|
||||
#
|
||||
# The timing and contents of a release are determined by the Consortium
|
||||
# staff based on the needs and desires of the Members and the advice of
|
||||
# the Advisory Board, tempered by the resource constraints of the
|
||||
# Consortium.
|
||||
#
|
||||
# Members have access to all X Consortium produced software and
|
||||
# documentation prior to release to the public. Each Member can receive
|
||||
# pre-releases and public releases at no charge. In addition, Members
|
||||
# have access to software and documentation while it is under
|
||||
# development, and can periodically request snapshots of the development
|
||||
# system at no charge.
|
||||
#
|
||||
# The X Consortium also maintains an electronic mail system for
|
||||
# reporting problems with X Consortium produced software and
|
||||
# documentation. Members have access to all bug reports, as well as all
|
||||
# software patches as they are incrementally developed by the Consortium
|
||||
# staff between releases.
|
||||
#
|
||||
# In general, all materials included in X Consortium releases are
|
||||
# copyrighted and contain permission notices granting unrestricted use,
|
||||
# sales and redistribution rights provided that the copyrights and the
|
||||
# permission notices are left intact. All materials are provided "as
|
||||
# is," without express or implied warranty.
|
||||
# --------------------------
|
||||
#
|
||||
# This accepts bsd-style install arguments and makes the appropriate calls
|
||||
# to the System V install.
|
||||
#
|
||||
|
||||
flags=""
|
||||
dst=""
|
||||
src=""
|
||||
dostrip=""
|
||||
owner=""
|
||||
mode=""
|
||||
|
||||
while [ x$1 != x ]; do
|
||||
case $1 in
|
||||
-c) shift
|
||||
continue;;
|
||||
|
||||
-m) flags="$flags $1 $2 "
|
||||
mode="$2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) flags="$flags -u $2 "
|
||||
owner="$2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) flags="$flags $1 $2 "
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) dostrip="strip"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x$src = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$mode" in
|
||||
"")
|
||||
;;
|
||||
*)
|
||||
case "$owner" in
|
||||
"")
|
||||
flags="$flags -u root"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ x$src = x ]
|
||||
then
|
||||
echo "$0: no input file specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x$dst = x ]
|
||||
then
|
||||
echo "$0: no destination specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
# set up some variable to be used later
|
||||
|
||||
rmcmd=""
|
||||
srcdir="."
|
||||
|
||||
# if the destination isn't a directory we'll need to copy it first
|
||||
|
||||
if [ ! -d $dst ]
|
||||
then
|
||||
dstbase=`basename $dst`
|
||||
cp $src /tmp/$dstbase
|
||||
rmcmd="rm -f /tmp/$dstbase"
|
||||
src=$dstbase
|
||||
srcdir=/tmp
|
||||
dst="`echo $dst | sed 's,^\(.*\)/.*$,\1,'`"
|
||||
if [ x$dst = x ]
|
||||
then
|
||||
dst="."
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
# If the src file has a directory, copy it to /tmp to make install happy
|
||||
|
||||
srcbase=`basename $src`
|
||||
|
||||
if [ "$src" != "$srcbase" -a "$src" != "./$srcbase" ]
|
||||
then
|
||||
cp $src /tmp/$srcbase
|
||||
src=$srcbase
|
||||
srcdir=/tmp
|
||||
rmcmd="rm -f /tmp/$srcbase"
|
||||
fi
|
||||
|
||||
# do the actual install
|
||||
|
||||
if [ -f /usr/sbin/install ]
|
||||
then
|
||||
installcmd=/usr/sbin/install
|
||||
elif [ -f /etc/install ]
|
||||
then
|
||||
installcmd=/etc/install
|
||||
else
|
||||
installcmd=install
|
||||
fi
|
||||
|
||||
# This rm is commented out because some people want to be able to
|
||||
# install through symbolic links. Uncomment it if it offends you.
|
||||
rm -f $dst/$srcbase
|
||||
(cd $srcdir ; $installcmd -f $dst $flags $src)
|
||||
|
||||
if [ x$dostrip = xstrip ]
|
||||
then
|
||||
strip $dst/$srcbase
|
||||
fi
|
||||
|
||||
# and clean up
|
||||
|
||||
$rmcmd
|
||||
|
||||
exit
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFILE="$FAKEROOT"$CONFIGED/pam.conf
|
||||
IGNORE_AGE=./.ignore_age
|
||||
CONF=./pam.conf
|
||||
|
||||
echo
|
||||
|
||||
if [ -f "$IGNORE_AGE" ]; then
|
||||
echo "you don't want to be bothered with the age of your $CONFILE file"
|
||||
yes="n"
|
||||
elif [ ! -f "$CONFILE" ] || [ "$CONF" -nt "$CONFILE" ]; then
|
||||
if [ -f "$CONFILE" ]; then
|
||||
echo "\
|
||||
An older Linux-PAM configuration file already exists ($CONFILE)"
|
||||
WRITE=overwrite
|
||||
fi
|
||||
echo -n "\
|
||||
Do you wish to copy the $CONF file in this distribution
|
||||
to $CONFILE ? (y/n) [n] "
|
||||
read yes
|
||||
else
|
||||
yes=n
|
||||
fi
|
||||
|
||||
if [ "$yes" = "y" ]; then
|
||||
echo " copying $CONF to $CONFILE"
|
||||
cp $CONF $CONFILE
|
||||
else
|
||||
touch "$IGNORE_AGE"
|
||||
echo " Skipping $CONF installation"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
@ -1,45 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# $Log$
|
||||
#
|
||||
# Created by Andrew G. Morgan (morgan@parc.power.net)
|
||||
#
|
||||
|
||||
MD5SUM=md5sum
|
||||
CHKFILE1=./.md5sum
|
||||
CHKFILE2=./.md5sum-new
|
||||
|
||||
which $MD5SUM > /dev/null
|
||||
result=$?
|
||||
|
||||
if [ -x "$MD5SUM" ] || [ $result -eq 0 ]; then
|
||||
rm -f $CHKFILE2
|
||||
echo -n "computing md5 checksums."
|
||||
for x in `cat ../.filelist` ; do
|
||||
(cd ../.. ; $MD5SUM $x) >> $CHKFILE2
|
||||
echo -n "."
|
||||
done
|
||||
echo
|
||||
if [ -f "$CHKFILE1" ]; then
|
||||
echo "\
|
||||
---> Note, since the last \`make check', the following file(s) have changed:
|
||||
==========================================================================="
|
||||
diff $CHKFILE1 $CHKFILE2
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "\
|
||||
--------------------------- Nothing has changed ---------------------------"
|
||||
fi
|
||||
echo "\
|
||||
==========================================================================="
|
||||
fi
|
||||
rm -f "$CHKFILE1"
|
||||
mv "$CHKFILE2" "$CHKFILE1"
|
||||
chmod 400 "$CHKFILE1"
|
||||
else
|
||||
echo "\
|
||||
Please install \`$MD5SUM'.
|
||||
[It is used to check the integrity of this distribution]
|
||||
---> no check done."
|
||||
fi
|
@ -1,50 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# this is a wrapper for difficult mkdir programs...
|
||||
#
|
||||
|
||||
for d in $*
|
||||
do
|
||||
if [ ! -d $d ]; then
|
||||
mkdir -p $d
|
||||
if [ $? -ne 0 ]; then exit $? ; fi
|
||||
fi
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
||||
##########################################################################
|
||||
# if your mkdir does not support the -p option delete the above lines and
|
||||
# use what follows:
|
||||
--------------------
|
||||
#!/bin/sh
|
||||
|
||||
#VERBOSE=yes
|
||||
Cwd=`pwd`
|
||||
|
||||
for d in $*
|
||||
do
|
||||
if [ "`echo $d|cut -c1`" != "/" ]; then
|
||||
x=`pwd`/$d
|
||||
else
|
||||
x=$d
|
||||
fi
|
||||
x="`echo $x|sed -e 'yX/X X'`"
|
||||
cd /
|
||||
for s in $x
|
||||
do
|
||||
if [ -d $s ]; then
|
||||
if [ -n "$VERBOSE" ]; then echo -n "[$s/]"; fi
|
||||
cd $s
|
||||
else
|
||||
mkdir $s
|
||||
if [ $? -ne 0 ]; then exit $? ; fi
|
||||
if [ -n "$VERBOSE" ]; then echo -n "$s/"; fi
|
||||
cd $s
|
||||
fi
|
||||
done
|
||||
if [ -n "$VERBOSE" ]; then echo ; fi
|
||||
cd $Cwd
|
||||
done
|
||||
|
||||
exit 0
|
@ -1,126 +0,0 @@
|
||||
# ---------------------------------------------------------------------------#
|
||||
# /etc/pam.conf #
|
||||
# #
|
||||
# Last modified by Andrew G. Morgan <morgan@parc.power.net> #
|
||||
# ---------------------------------------------------------------------------#
|
||||
# $Id: pam.conf,v 1.18 1997/02/15 20:20:20 morgan Exp morgan $
|
||||
# ---------------------------------------------------------------------------#
|
||||
# serv. module ctrl module [path] ...[args..] #
|
||||
# name type flag #
|
||||
# ---------------------------------------------------------------------------#
|
||||
#
|
||||
# The PAM configuration file for the `chfn' service
|
||||
#
|
||||
chfn auth required pam_pwdb.so
|
||||
chfn account required pam_pwdb.so
|
||||
chfn password required pam_cracklib.so retry=3
|
||||
chfn password required pam_pwdb.so shadow md5 use_authtok
|
||||
#
|
||||
# The PAM configuration file for the `chsh' service
|
||||
#
|
||||
chsh auth required pam_pwdb.so
|
||||
chsh account required pam_pwdb.so
|
||||
chsh password required pam_cracklib.so retry=3
|
||||
chsh password required pam_pwdb.so shadow md5 use_authtok
|
||||
#
|
||||
# The PAM configuration file for the `ftp' service
|
||||
#
|
||||
ftp auth requisite pam_listfile.so \
|
||||
item=user sense=deny file=/etc/ftpusers onerr=succeed
|
||||
ftp auth requisite pam_shells.so
|
||||
ftp auth required pam_pwdb.so
|
||||
ftp account required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `imap' service
|
||||
#
|
||||
imap auth required pam_pwdb.so
|
||||
imap account required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `login' service
|
||||
#
|
||||
login auth requisite pam_securetty.so
|
||||
login auth required pam_pwdb.so
|
||||
login auth optional pam_group.so
|
||||
login account requisite pam_time.so
|
||||
login account required pam_pwdb.so
|
||||
login password required pam_cracklib.so retry=3
|
||||
login password required pam_pwdb.so shadow md5 use_authtok
|
||||
login session required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `netatalk' service
|
||||
#
|
||||
netatalk auth required pam_pwdb.so
|
||||
netatalk account required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `other' service
|
||||
#
|
||||
other auth required pam_deny.so
|
||||
other auth required pam_warn.so
|
||||
other account required pam_deny.so
|
||||
other password required pam_deny.so
|
||||
other password required pam_warn.so
|
||||
other session required pam_deny.so
|
||||
#
|
||||
# The PAM configuration file for the `passwd' service
|
||||
#
|
||||
passwd password requisite pam_cracklib.so retry=3
|
||||
passwd password required pam_pwdb.so shadow md5 use_authtok
|
||||
#
|
||||
# The PAM configuration file for the `rexec' service
|
||||
#
|
||||
rexec auth requisite pam_securetty.so
|
||||
rexec auth requisite pam_nologin.so
|
||||
rexec auth sufficient pam_rhosts_auth.so
|
||||
rexec auth required pam_pwdb.so
|
||||
rexec account required pam_pwdb.so
|
||||
rexec session required pam_pwdb.so
|
||||
rexec session required pam_limits.so
|
||||
#
|
||||
# The PAM configuration file for the `rlogin' service
|
||||
# this application passes control to `login' if it fails
|
||||
#
|
||||
rlogin auth requisite pam_securetty.so
|
||||
rlogin auth requisite pam_nologin.so
|
||||
rlogin auth required pam_rhosts_auth.so
|
||||
rlogin account required pam_pwdb.so
|
||||
rlogin password required pam_cracklib.so retry=3
|
||||
rlogin password required pam_pwdb.so shadow md5 use_authtok
|
||||
rlogin session required pam_pwdb.so
|
||||
rlogin session required pam_limits.so
|
||||
#
|
||||
# The PAM configuration file for the `rsh' service
|
||||
#
|
||||
rsh auth requisite pam_securetty.so
|
||||
rsh auth requisite pam_nologin.so
|
||||
rsh auth sufficient pam_rhosts_auth.so
|
||||
rsh auth required pam_pwdb.so
|
||||
rsh account required pam_pwdb.so
|
||||
rsh session required pam_pwdb.so
|
||||
rsh session required pam_limits.so
|
||||
#
|
||||
# The PAM configuration file for the `samba' service
|
||||
#
|
||||
samba auth required pam_pwdb.so
|
||||
samba account required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `su' service
|
||||
#
|
||||
su auth required pam_wheel.so
|
||||
su auth sufficient pam_rootok.so
|
||||
su auth required pam_pwdb.so
|
||||
su account required pam_pwdb.so
|
||||
su session required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `vlock' service
|
||||
#
|
||||
vlock auth required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `xdm' service
|
||||
#
|
||||
xdm auth required pam_pwdb.so
|
||||
xdm account required pam_pwdb.so
|
||||
#
|
||||
# The PAM configuration file for the `xlock' service
|
||||
#
|
||||
xlock auth required pam_pwdb.so
|
||||
|
@ -1,41 +0,0 @@
|
||||
#
|
||||
#
|
||||
ifeq ($(OS),solaris)
|
||||
|
||||
clean:
|
||||
@echo not available in Solaris
|
||||
|
||||
all:
|
||||
@echo not available in Solaris
|
||||
|
||||
install:
|
||||
@echo not available in Solaris
|
||||
|
||||
else
|
||||
|
||||
all: pam_conv1
|
||||
|
||||
pam_conv1: pam_conv.tab.c lex.yy.c
|
||||
$(CC) -o pam_conv1 pam_conv.tab.c -lfl
|
||||
|
||||
pam_conv.tab.c: pam_conv.y lex.yy.c
|
||||
bison pam_conv.y
|
||||
|
||||
lex.yy.c: pam_conv.lex
|
||||
flex pam_conv.lex
|
||||
|
||||
lclean:
|
||||
rm -f core pam_conv1 lex.yy.c pam_conv.tab.c *.o *~
|
||||
rm -rf ./pam.d pam_conv.output
|
||||
|
||||
clean: lclean
|
||||
|
||||
install: pam_conv1
|
||||
cp -f ./pam_conv1 ../../bin
|
||||
|
||||
endif
|
||||
|
||||
remove:
|
||||
rm -f ../../bin/pam_conv1
|
||||
|
||||
extraclean: remove clean
|
@ -1,10 +0,0 @@
|
||||
$Id: README,v 1.1 1997/02/15 15:50:50 morgan Exp $
|
||||
|
||||
This directory contains a untility to convert pam.conf files to a pam.d/
|
||||
tree. The conversion program takes pam.conf from the standard input and
|
||||
creates the pam.d/ directory in the current directory.
|
||||
|
||||
The program will fail if ./pam.d/ already exists.
|
||||
|
||||
Andrew Morgan, February 1997
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,42 +0,0 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* $Id: pam_conv.lex,v 1.1 1997/01/23 05:35:50 morgan Exp $
|
||||
*
|
||||
* Copyright (c) Andrew G. Morgan 1997 <morgan@parc.power.net>
|
||||
*
|
||||
* This file is covered by the Linux-PAM License (which should be
|
||||
* distributed with this file.)
|
||||
*/
|
||||
|
||||
const static char lexid[]=
|
||||
"$Id: pam_conv.lex,v 1.1 1997/01/23 05:35:50 morgan Exp $\n"
|
||||
"Copyright (c) Andrew G. Morgan 1997 <morgan@parc.power.net>\n";
|
||||
|
||||
extern int current_line;
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
"#"[^\n]* ; /* skip comments (sorry) */
|
||||
|
||||
"\\\n" {
|
||||
++current_line;
|
||||
}
|
||||
|
||||
([^\n\t ]|[\\][^\n])+ {
|
||||
return TOK;
|
||||
}
|
||||
|
||||
[ \t]+ ; /* Ignore */
|
||||
|
||||
<<EOF>> {
|
||||
return EOFILE;
|
||||
}
|
||||
|
||||
[\n] {
|
||||
++current_line;
|
||||
return NL;
|
||||
}
|
||||
|
||||
%%
|
File diff suppressed because it is too large
Load Diff
@ -1,203 +0,0 @@
|
||||
%{
|
||||
|
||||
/*
|
||||
* $Id: pam_conv.y,v 1.3 1997/02/15 15:50:50 morgan Exp morgan $
|
||||
*
|
||||
* Copyright (c) Andrew G. Morgan 1997 <morgan@parc.power.net>
|
||||
*
|
||||
* This file is covered by the Linux-PAM License (which should be
|
||||
* distributed with this file.)
|
||||
*/
|
||||
|
||||
const static char bisonid[]=
|
||||
"$Id: pam_conv.y,v 1.3 1997/02/15 15:50:50 morgan Exp morgan $\n"
|
||||
"Copyright (c) Andrew G. Morgan 1997-8 <morgan@linux.kernel.org>\n";
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int current_line=1;
|
||||
extern char *yytext;
|
||||
|
||||
/* XXX - later we'll change this to be the specific conf file(s) */
|
||||
#define newpamf stderr
|
||||
|
||||
#define PAM_D "./pam.d"
|
||||
#define PAM_D_MODE 0755
|
||||
#define PAM_D_MAGIC_HEADER \
|
||||
"#%PAM-1.0\n" \
|
||||
"#[For version 1.0 syntax, the above header is optional]\n"
|
||||
|
||||
#define PAM_D_FILE_FMT PAM_D "/%s"
|
||||
|
||||
const char *old_to_new_ctrl_flag(const char *old);
|
||||
void yyerror(const char *format, ...);
|
||||
%}
|
||||
|
||||
%union {
|
||||
int def;
|
||||
char *string;
|
||||
}
|
||||
|
||||
%token NL EOFILE TOK
|
||||
|
||||
%type <string> tok path tokenls
|
||||
|
||||
%start complete
|
||||
|
||||
%%
|
||||
|
||||
complete
|
||||
:
|
||||
| complete NL
|
||||
| complete line
|
||||
| complete EOFILE {
|
||||
return 0;
|
||||
}
|
||||
;
|
||||
|
||||
line
|
||||
: tok tok tok path tokenls NL {
|
||||
char *filename;
|
||||
FILE *conf;
|
||||
int i;
|
||||
|
||||
/* make sure we have lower case */
|
||||
for (i=0; $1[i]; ++i) {
|
||||
$1[i] = tolower($1[i]);
|
||||
}
|
||||
|
||||
/* $1 = service-name */
|
||||
yyerror("Appending to " PAM_D "/%s", $1);
|
||||
|
||||
filename = malloc(strlen($1) + sizeof(PAM_D) + 6);
|
||||
sprintf(filename, PAM_D_FILE_FMT, $1);
|
||||
conf = fopen(filename, "r");
|
||||
if (conf == NULL) {
|
||||
/* new file */
|
||||
conf = fopen(filename, "w");
|
||||
if (conf != NULL) {
|
||||
fprintf(conf, PAM_D_MAGIC_HEADER);
|
||||
fprintf(conf,
|
||||
"#\n"
|
||||
"# The PAM configuration file for the `%s' service\n"
|
||||
"#\n", $1);
|
||||
}
|
||||
} else {
|
||||
fclose(conf);
|
||||
conf = fopen(filename, "a");
|
||||
}
|
||||
if (conf == NULL) {
|
||||
yyerror("trouble opening %s - aborting", filename);
|
||||
exit(1);
|
||||
}
|
||||
free(filename);
|
||||
|
||||
/* $2 = module-type */
|
||||
fprintf(conf, "%-10s", $2);
|
||||
free($2);
|
||||
|
||||
/* $3 = required etc. */
|
||||
{
|
||||
const char *trans;
|
||||
|
||||
trans = old_to_new_ctrl_flag($3);
|
||||
free($3);
|
||||
fprintf(conf, " %-10s", trans);
|
||||
}
|
||||
|
||||
/* $4 = module-path */
|
||||
fprintf(conf, " %s", $4);
|
||||
free($4);
|
||||
|
||||
/* $5 = arguments */
|
||||
if ($5 != NULL) {
|
||||
fprintf(conf, " \\\n\t\t%s", $5);
|
||||
free($5);
|
||||
}
|
||||
|
||||
/* end line */
|
||||
fprintf(conf, "\n");
|
||||
|
||||
fclose(conf);
|
||||
}
|
||||
| error NL {
|
||||
yyerror("malformed line");
|
||||
}
|
||||
;
|
||||
|
||||
tokenls
|
||||
: {
|
||||
$$=NULL;
|
||||
}
|
||||
| tokenls tok {
|
||||
int len;
|
||||
|
||||
if ($1) {
|
||||
len = strlen($1) + strlen($2) + 2;
|
||||
$$ = malloc(len);
|
||||
sprintf($$,"%s %s",$1,$2);
|
||||
free($1);
|
||||
free($2);
|
||||
} else {
|
||||
$$ = $2;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
path
|
||||
: TOK {
|
||||
/* XXX - this could be used to check if file present */
|
||||
$$ = strdup(yytext);
|
||||
}
|
||||
|
||||
tok
|
||||
: TOK {
|
||||
$$ = strdup(yytext);
|
||||
}
|
||||
|
||||
%%
|
||||
|
||||
#include "lex.yy.c"
|
||||
|
||||
const char *old_to_new_ctrl_flag(const char *old)
|
||||
{
|
||||
static const char *clist[] = {
|
||||
"requisite",
|
||||
"required",
|
||||
"sufficient",
|
||||
"optional",
|
||||
NULL,
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i=0; clist[i]; ++i) {
|
||||
if (strcasecmp(clist[i], old) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return clist[i];
|
||||
}
|
||||
|
||||
void yyerror(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
fprintf(stderr, "line %d: ", current_line);
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
va_end(args);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if (mkdir(PAM_D, PAM_D_MODE) != 0) {
|
||||
yyerror(PAM_D " already exists.. aborting");
|
||||
exit(1);
|
||||
}
|
||||
yyparse();
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
##
|
||||
# HPUX defs contributed by Derrick J Brashear <shadow@dementia.org>
|
||||
##
|
||||
# this file indicates the compiler and the various hardware/OS dependent
|
||||
# flags for installation. It also defines the various destinations of
|
||||
# installed files on the system.
|
||||
#
|
||||
# This file is the default version. Please look in .../defs/ for your
|
||||
# preferred OS/vendor.
|
||||
|
||||
OS=hpux9
|
||||
ARCH=hpux
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
MKDIR=mkdir -p
|
||||
CFLAGS=-g -DPAM_SHL -DHAVE_UTMP_H
|
||||
ULIBS=
|
||||
LD=ld
|
||||
LD_D=$(LD) -b
|
||||
LD_L=$(LD) -b
|
||||
USESONAME=no
|
||||
NEEDSONAME=no
|
||||
LDCONFIG=:
|
||||
AR=ar -cr
|
||||
RANLIB=ranlib
|
||||
FAKEROOT=
|
||||
PREFIX=/usr
|
||||
SUPLEMENTED=$(PREFIX)/sbin
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
SECUREDIR=$(LIBDIR)/security
|
||||
INCLUDED=/usr/include/security
|
||||
CONFIGED=/etc
|
||||
SCONFIGED=/etc/security
|
||||
DYNLOAD="dld"
|
||||
DYNTYPE="sl"
|
||||
SHLIBMODE=755
|
@ -1,32 +0,0 @@
|
||||
# this file indicates the compiler and the various hardware/OS dependent
|
||||
# flags for installation. It also defines the various destinations of
|
||||
# installed files on the system.
|
||||
#
|
||||
# This file is the default version. Please look in .../defs/ for your
|
||||
# preferred OS/vendor.
|
||||
|
||||
OS=linux
|
||||
ARCH=`uname -m | sed 's/^i?86/i386/'`
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
MKDIR=mkdir -p
|
||||
CFLAGS=-O7 -pipe -g
|
||||
ULIBS=#-lefence
|
||||
LD=ld
|
||||
LD_D=gcc -shared -Xlinker -x
|
||||
LD_L=$(LD) -x -shared
|
||||
USESONAME=yes
|
||||
SOSWITCH=-soname
|
||||
NEEDSONAME=no
|
||||
LDCONFIG=/sbin/ldconfig
|
||||
AR=ar -cr
|
||||
RANLIB=ranlib
|
||||
FAKEROOT=
|
||||
PREFIX=/usr
|
||||
SUPLEMENTED=$(PREFIX)/sbin
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
SECUREDIR=$(LIBDIR)/security
|
||||
INCLUDED=/usr/include/security
|
||||
CONFIGED=/etc
|
||||
SCONFIGED=/etc/security
|
||||
NSLLIB=-lnsl
|
@ -1,35 +0,0 @@
|
||||
##
|
||||
# defs for Andrew's debugging version (which is a modified Red Hat
|
||||
# box)
|
||||
##
|
||||
# this file indicates the compiler and the various hardware/OS dependent
|
||||
# flags for installation. It also defines the various destinations of
|
||||
# installed files on the system.
|
||||
#
|
||||
# This file is the version used for Red Hat Linux.
|
||||
|
||||
OS=linux
|
||||
ARCH=i386
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
MKDIR=mkdir -p
|
||||
CFLAGS=$(RPM_OPT_FLAGS) -pipe -g
|
||||
ULIBS=
|
||||
#-lefence
|
||||
LD=ld
|
||||
LD_D=gcc -shared -Xlinker -x
|
||||
LD_L=$(LD) -x -shared
|
||||
USESONAME=yes
|
||||
SOSWITCH=-soname
|
||||
NEEDSONAME=no
|
||||
LDCONFIG=/sbin/ldconfig
|
||||
AR=ar -cr
|
||||
RANLIB=ranlib
|
||||
FAKEROOT=$(RPM_BUILD_ROOT)
|
||||
PREFIX=
|
||||
SUPLEMENTED=$(PREFIX)/sbin
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
SECUREDIR=$(LIBDIR)/security.d
|
||||
INCLUDED=/usr/include/security
|
||||
CONFIGED=/etc
|
||||
SCONFIGED=/etc/security
|
@ -1,34 +0,0 @@
|
||||
##
|
||||
# defs for Red Hat Linux
|
||||
# Michael K. Johnson <johnsonm@redhat.com>
|
||||
##
|
||||
# this file indicates the compiler and the various hardware/OS dependent
|
||||
# flags for installation. It also defines the various destinations of
|
||||
# installed files on the system.
|
||||
#
|
||||
# This file is the version used for Red Hat Linux.
|
||||
|
||||
OS=linux
|
||||
ARCH=$(shell rpm --showrc | grep 'build arch' | sed 's/^.*: //g')
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
MKDIR=mkdir -p
|
||||
CFLAGS=$(RPM_OPT_FLAGS) -pipe -g
|
||||
ULIBS=#-lefence
|
||||
LD=ld
|
||||
LD_D=gcc -shared -Xlinker -x
|
||||
LD_L=$(LD) -x -shared
|
||||
USESONAME=yes
|
||||
SOSWITCH=-soname
|
||||
NEEDSONAME=no
|
||||
LDCONFIG=/sbin/ldconfig
|
||||
AR=ar -cr
|
||||
RANLIB=ranlib
|
||||
FAKEROOT=$(RPM_BUILD_ROOT)
|
||||
PREFIX=
|
||||
SUPLEMENTED=$(PREFIX)/sbin
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
SECUREDIR=$(LIBDIR)/security
|
||||
INCLUDED=/usr/include/security
|
||||
CONFIGED=/etc
|
||||
SCONFIGED=/etc/security
|
@ -1,48 +0,0 @@
|
||||
##
|
||||
# Solaris defs contributed by Josh Wilmes <josh@makita.jpl.nasa.gov>
|
||||
##
|
||||
# this file indicates the compiler and the various hardware/OS dependent
|
||||
# flags for installation. It also defines the various destinations of
|
||||
# installed files on the system.
|
||||
#
|
||||
# This file is the default version. Please look in .../defs/ for your
|
||||
# preferred OS/vendor.
|
||||
|
||||
# Please note that the linker used must be the GNU ld, not the native Sun
|
||||
# linker. It is fairly common for the gnu linker (/usr/ccs/bin/ld) to be
|
||||
# configured as the default linker for gcc. To tell gcc to use the
|
||||
# gnu linker, you need to set the GCC_EXEC_PREFIX environment variable
|
||||
# to point at the directory where the gnu linker is installed. Here's
|
||||
# what I do:
|
||||
# $ mkdir /tmp/foo
|
||||
# $ ln -s /path/to/gnu/ld /tmp/foo/ld
|
||||
# $ export GCC_EXEC_PREFIX=/tmp/foo/
|
||||
# $ export PATH=/tmp/foo:$PATH
|
||||
|
||||
OS=solaris
|
||||
ARCH=sun
|
||||
CC=cc
|
||||
INSTALL=install
|
||||
MKDIR=mkdir -p
|
||||
WARNINGS = -D_POSIX_SOURCE
|
||||
PIC=-KPIC
|
||||
CFLAGS=-g -D__EXTENSIONS__ -Dsolaris
|
||||
ULIBS=
|
||||
LD=ld
|
||||
LD_L=$(LD) -G
|
||||
LD_D=$(LD_L)
|
||||
RDYNAMIC=
|
||||
USESONAME=yes
|
||||
SOSWITCH=-h
|
||||
NEEDSONAME=no
|
||||
LDCONFIG=echo
|
||||
AR=ar -cr
|
||||
RANLIB=ranlib
|
||||
FAKEROOT=
|
||||
PREFIX=/usr
|
||||
SUPLEMENTED=$(PREFIX)/sbin
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
SECUREDIR=$(LIBDIR)/security
|
||||
INCLUDED=/usr/include/security
|
||||
CONFIGED=/etc
|
||||
SCONFIGED=/etc/security
|
@ -1,37 +0,0 @@
|
||||
##
|
||||
# SunOS defs contributed by Derrick J Brashear <shadow@dementia.org>
|
||||
##
|
||||
# this file indicates the compiler and the various hardware/OS dependent
|
||||
# flags for installation. It also defines the various destinations of
|
||||
# installed files on the system.
|
||||
#
|
||||
# This file is the SunOS version. Please look in .../defs/ for your
|
||||
# preferred OS/vendor.
|
||||
|
||||
OS=sunos
|
||||
ARCH=sun
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
MKDIR=mkdir -p
|
||||
CFLAGS=-O2 -pipe -g -D__EXTENSIONS__
|
||||
ULIBS=
|
||||
LD_D=gcc -shared -Xlinker -x
|
||||
LD=ld
|
||||
LD_L=$(LD)
|
||||
USESONAME=no
|
||||
NEEDSONAME=yes
|
||||
LDCONFIG=/usr/etc/ldconfig
|
||||
AR=ar cr
|
||||
RANLIB=ranlib
|
||||
FAKEROOT=
|
||||
PREFIX=/usr
|
||||
SUPLEMENTED=$(PREFIX)/sbin
|
||||
LIBDIR=$(PREFIX)/lib
|
||||
SECUREDIR=$(LIBDIR)/security
|
||||
INCLUDED=/usr/include/security
|
||||
CONFIGED=/etc
|
||||
SCONFIGED=/etc/security
|
||||
WARNINGS= -ansi -Wall -Wwrite-strings \
|
||||
-Wpointer-arith -Wcast-qual -Wcast-align \
|
||||
-Wtraditional -Wstrict-prototypes -Wmissing-prototypes \
|
||||
-Wnested-externs -Winline -Wshadow
|
@ -1,13 +0,0 @@
|
||||
$Id: README,v 1.2 1996/11/17 17:20:28 morgan Exp $
|
||||
|
||||
This directory contains a number of sgml sub-files. One for each
|
||||
documented module. They contain a description of each module and give
|
||||
some indication of its reliability.
|
||||
|
||||
Additionally, there is a 'module.sgml-template' file which should be
|
||||
used as a blank form for new module descriptions.
|
||||
|
||||
Please feel free to submit amendments/comments etc. regarding these
|
||||
files to:
|
||||
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
@ -1,170 +0,0 @@
|
||||
<!--
|
||||
|
||||
$Id: module.sgml-template,v 1.1 1996/11/30 20:59:32 morgan Exp $
|
||||
|
||||
This template file was written by Andrew G. Morgan
|
||||
<morgan@parc.power.net>
|
||||
|
||||
[
|
||||
Text that should be deleted/replaced, is enclosed within
|
||||
'[' .. ']'
|
||||
marks. For example, this text should be deleted!
|
||||
]
|
||||
|
||||
-->
|
||||
|
||||
<sect1> [*Familiar full name of module*, eg. The "allow all" module.]
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
[
|
||||
insert the name of the module
|
||||
|
||||
Blank is not permitted.
|
||||
]
|
||||
|
||||
<tag><bf>Author[s]:</bf></tag>
|
||||
|
||||
[
|
||||
Insert author names here
|
||||
|
||||
Blank is not permitted. If in doubt, put "unknown" if the
|
||||
author wishes to remain anonymous, put "anonymous".
|
||||
]
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
|
||||
[
|
||||
Insert names and date-begun of most recent maintainer.
|
||||
]
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
|
||||
[
|
||||
list the subset of four management groups supported by the
|
||||
module. Choose from: account; authentication; password;
|
||||
session.
|
||||
|
||||
Blank entries are not permitted. Explicitly list all of the
|
||||
management groups. In the future more may be added to libpam!
|
||||
]
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
[
|
||||
Indicate whether this module contains code that can perform
|
||||
reversible (strong) encryption. This field is primarily to
|
||||
ensure that people redistributing it are not unwittingly
|
||||
breaking laws...
|
||||
|
||||
Modules may also require the presence of some local library
|
||||
that performs the necessary encryption via some standard API.
|
||||
In this case "uses API" can be included in this field. The
|
||||
library in question should be added to the system requirements
|
||||
below.
|
||||
|
||||
Blank = no cryptography is used by module.
|
||||
]
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
[
|
||||
Initially, this field should be left blank. If someone takes
|
||||
it upon themselves to test the strength of the module, it can
|
||||
later be filled.
|
||||
|
||||
Blank = unknown.
|
||||
]
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
[
|
||||
This will probably be filled by the libpam maintainer.
|
||||
It can be considered to be a public humiliation list. :*)
|
||||
|
||||
I am of the opinion that "gcc -with_all_those_flags" is
|
||||
trying to tell us something about whether the program
|
||||
works as intended. Since there is currently no Security
|
||||
evaluation procedure for modules IMHO this is not a
|
||||
completely unreasonable indication (a lower bound anyway)
|
||||
of the reliability of a module.
|
||||
|
||||
This field would indicate the number and flavor of
|
||||
warnings that gcc barfs up when trying to compile the
|
||||
module as part of the tree. Is this too tyrannical?
|
||||
|
||||
Blank = Linux-PAM maintainer has not tested it :)
|
||||
]
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
[
|
||||
here we list config files, dynamic libraries needed, system
|
||||
resources, kernel options.. etc.
|
||||
|
||||
Blank = nothing more than libc required.
|
||||
]
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
[
|
||||
Does the module base its behavior on probing a network
|
||||
connection? Does it expect to be protected by the
|
||||
application?
|
||||
|
||||
Blank = Ignorance of network.
|
||||
]
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
[
|
||||
some text describing the intended actions of the module
|
||||
general comments mainly (specifics in sections
|
||||
below).
|
||||
]
|
||||
|
||||
[
|
||||
|
||||
[ now we have a <sect2> level subsection for each of the
|
||||
management groups. Include as many as there are groups
|
||||
listed above in the synopsis ]
|
||||
|
||||
<sect2>[ Account | Authentication | Password | Session ] component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
[
|
||||
List the supported arguments (leave their description for the
|
||||
description below.
|
||||
|
||||
Blank = no arguments are read and nothing is logged to syslog
|
||||
about any arguments that are passed. Note, this
|
||||
behavior is contrary to the RFC!
|
||||
]
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
[
|
||||
This component of the module performs the task of ...
|
||||
]
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
[
|
||||
Here we list some doos and don'ts for this module.
|
||||
]
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,86 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_chroot.sgml,v 1.1 1996/11/30 20:59:32 morgan Exp $
|
||||
|
||||
This file was written by Bruce Campbell <brucec@humbug.org.au>
|
||||
-->
|
||||
|
||||
<sect1>Chroot
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_chroot/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Bruce Campbell <brucec@humbug.org.au>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author; proposed on 20/11/96 - email for status
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
account; session; authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
Unwritten.
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
Expects localhost.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module is intended to provide a transparent wrapper around the
|
||||
average user, one that puts them in a fake file-system (eg, their
|
||||
'<tt>/</tt>' is really <tt>/some/where/else</tt>).
|
||||
|
||||
<p>
|
||||
Useful if you have several classes of users, and are slightly paranoid
|
||||
about security. Can be used to limit who else users can see on the
|
||||
system, and to limit the selection of programs they can run.
|
||||
|
||||
<sect2>Account component:
|
||||
|
||||
<p>
|
||||
<em/Need more info here./
|
||||
|
||||
<sect2>Authentication component:
|
||||
|
||||
<p>
|
||||
<em/Need more info here./
|
||||
|
||||
<sect2>Session component:
|
||||
|
||||
<p>
|
||||
<em/Need more info here./
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
Arguments and logging levels for the PAM version are being worked on.
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
Do provide a reasonable list of programs - just tossing 'cat', 'ls', 'rm',
|
||||
'cp' and 'ed' in there is a bit...
|
||||
<p>
|
||||
Don't take it to extremes (eg, you can set up a separate environment for
|
||||
each user, but its a big waste of your disk space.)
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,254 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_cracklib.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp morgan $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
long password amendments are from Philip W. Dalrymple III <pwd@mdtsoft.com>
|
||||
-->
|
||||
|
||||
<sect1>Cracklib pluggable password strength-checker
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
|
||||
pam_cracklib
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
|
||||
Cristian Gafton <gafton@redhat.com>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
|
||||
password
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
Requires the system library <tt/libcrack/ and a system dictionary:
|
||||
<tt>/usr/lib/cracklib_dict</tt>.
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module can be plugged into the <tt/password/ stack of a given
|
||||
application to provide some plug-in strength-checking for passwords.
|
||||
(XXX - note this does not necessarily work with the pam_unix module,
|
||||
although it is known to work with the pam_pwdb replacement for the
|
||||
unix module -- see example and pam_pwdb write up for more
|
||||
information).
|
||||
|
||||
<p>
|
||||
This module works in the following manner: it first calls the
|
||||
<em>Cracklib</em> routine to check the strength of the password; if
|
||||
crack likes the password, the module does an additional set of
|
||||
strength checks. These checks are:
|
||||
<itemize>
|
||||
|
||||
<item> <bf/Palindrome/ -
|
||||
|
||||
Is the new password a palindrome of the old one?
|
||||
|
||||
<item> <bf/Case Change Only/ -
|
||||
|
||||
Is the new password the the old one with only a change of case?
|
||||
|
||||
<item> <bf/Similar/ -
|
||||
|
||||
Is the new password too much like the old one? This is controlled
|
||||
by one argument, <tt/difok/ which is a number of characters that if
|
||||
different between the old and new are enough to accept the new
|
||||
password, this defaults to 10 or 1/2 the size of the new password
|
||||
whichever is smaller.
|
||||
|
||||
<item <bf/Simple/ -
|
||||
|
||||
Is the new password too small? This is controlled by 5 arguments
|
||||
<tt/minlen/, <tt/dcredit/, <tt/ucredit/, <tt/lcredit/, and
|
||||
<tt/ocredit/. See the section on the arguments for the details of how
|
||||
these work and there defaults.
|
||||
|
||||
<item <bf/Rotated/ -
|
||||
|
||||
Is the new password a rotated version of the old password?
|
||||
|
||||
</itemize>
|
||||
|
||||
<p>
|
||||
This module with no arguments will work well for standard unix
|
||||
password encryption. With md5 encryption, passwords can be longer
|
||||
than 8 characters and the default settings for this module can make it
|
||||
hard for the user to choose a satisfactory new password. Notably, the
|
||||
requirement that the new password contain no more than 1/2 of the
|
||||
characters in the old password becomes a non-trivial constraint. For
|
||||
example, an old password of the form "the quick brown fox jumped over
|
||||
the lazy dogs" would be difficult to change... In addition, the
|
||||
default action is to allow passwords as small as 5 characters in
|
||||
length. For a md5 systems it can be a good idea to increase the
|
||||
required minimum size of a password. One can then allow more credit
|
||||
for different kinds of characters but accept that the new password may
|
||||
share most of these characters with the old password.
|
||||
|
||||
<sect2>Password component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tt/debug/; <tt/type=XXX/; <tt/retry=N/; <tt/difok=N/; <tt/minlen=N/;
|
||||
<tt/dcredit=N/; <tt/ucredit=N/; <tt/lcredit=N/; <tt/ocredit=N/;
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
The action of this module is to prompt the user for a password and
|
||||
check its strength against a system dictionary and a set of rules for
|
||||
identifying poor choices.
|
||||
|
||||
<p>
|
||||
The default action is to prompt for a single password, check its
|
||||
strength and then, if it is considered strong, prompt for the password
|
||||
a second time (to verify that it was typed correctly on the first
|
||||
occasion). All being well, the password is passed on to subsequent
|
||||
modules to be installed as the new authentication token.
|
||||
|
||||
<p>
|
||||
The default action may be modified in a number of ways using the
|
||||
arguments recognized by the module:
|
||||
<itemize>
|
||||
|
||||
<item> <tt/debug/ -
|
||||
|
||||
this option makes the module write information to syslog(3) indicating
|
||||
the behavior of the module (this option does <bf/not/ write password
|
||||
information to the log file).
|
||||
|
||||
<item> <tt/type=XXX/ -
|
||||
|
||||
the default action is for the module to use the following prompts when
|
||||
requesting passwords: ``New UNIX password: '' and ``Retype UNIX
|
||||
password: ''. Using this option you can replace the word UNIX with
|
||||
<tt/XXX/.
|
||||
|
||||
<item> <tt/retry=N/ -
|
||||
|
||||
the default number of times this module will request a new password
|
||||
(for strength-checking) from the user is 1. Using this argument this
|
||||
can be increased to <tt/N/.
|
||||
|
||||
<item> <tt/difok=N/ -
|
||||
|
||||
This argument will change the default of 10 for the number of
|
||||
characters in the new password that must not be present in the old
|
||||
password. In addition, if 1/2 of the characters in the new password
|
||||
are different then the new password will be accepted anyway.
|
||||
|
||||
<item> <tt/minlen=N/ -
|
||||
|
||||
The minimum acceptable size for the new password plus one. In
|
||||
addition to the number of characters in the new password, credit (of
|
||||
+1 in length) is given for each different kind of character (<em>other,
|
||||
upper, lower</em> and <em/digit/). The default for this parameter is
|
||||
9 which is good for a old style UNIX password all of the same type of
|
||||
character but may be too low to exploit the added security of a md5
|
||||
system. Note that there is a pair of length limits in
|
||||
<em>Cracklib</em> itself, a "way too short" limit of 4 which is hard
|
||||
coded in and a defined limit (6) that will be checked without
|
||||
reference to <tt>minlen</tt>. If you want to allow passwords as short
|
||||
as 5 characters you should either not use this module or recompile
|
||||
the crack library and then recompile this module.
|
||||
|
||||
<item> <tt/dcredit=N/ -
|
||||
|
||||
This is the maximum credit for having digits in the new password. If
|
||||
you have less than or <tt/N/ digits, each digit will count +1 towards
|
||||
meeting the current <tt/minlen/ value. The default for <tt/dcredit/
|
||||
is 1 which is the recommended value for <tt/minlen/ less than 10.
|
||||
|
||||
<item> <tt/ucredit=N/ -
|
||||
|
||||
This is the maximum credit for having upper case letters in the new
|
||||
password. If you have less than or <tt/N/ upper case letters each
|
||||
letter will count +1 towards meeting the current <tt/minlen/ value.
|
||||
The default for <tt/ucredit/ is 1 which is the recommended value for
|
||||
<tt/minlen/ less than 10.
|
||||
|
||||
<item> <tt/lcredit=N/ -
|
||||
|
||||
This is the maximum credit for having lower case letters in the new
|
||||
password. If you have less than or <tt/N/ lower case letters, each
|
||||
letter will count +1 towards meeting the current <tt/minlen/ value.
|
||||
The default for <tt/lcredit/ is 1 which is the recommended value for
|
||||
<tt/minlen/ less than 10.
|
||||
|
||||
<item> <tt/ocredit=N/ -
|
||||
|
||||
This is the maximum credit for having other characters in the new
|
||||
password. If you have less than or <tt/N/ other characters, each
|
||||
character will count +1 towards meeting the current <tt/minlen/ value.
|
||||
The default for <tt/ocredit/ is 1 which is the recommended value for
|
||||
<tt/minlen/ less than 10.
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
(At the time of writing, this module can only be stacked before the
|
||||
<tt/pam_pwdb/ module. Cracklib strength checking may be compiled by
|
||||
default into the <tt/pam_unix/ module.)
|
||||
|
||||
<p>
|
||||
For an example of the use of this module, we show how it may be
|
||||
stacked with the password component of <tt/pam_pwdb/:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# These lines stack two password type modules. In this example the
|
||||
# user is given 3 opportunities to enter a strong password. The
|
||||
# "use_authtok" argument ensures that the pam_pwdb module does not
|
||||
# prompt for a password, but instead uses the one provided by
|
||||
# pam_cracklib.
|
||||
#
|
||||
passwd password required pam_cracklib.so retry=3
|
||||
passwd password required pam_pwdb.so use_authtok
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
<p>
|
||||
Another example (in the <tt>/etc/pam.d/passwd</tt> format) is for the
|
||||
case that you want to use md5 password encryption:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#%PAM-1.0
|
||||
#
|
||||
# These lines allow a md5 systems to support passwords of at least 14
|
||||
# bytes with extra credit of 2 for digits and 2 for others the new
|
||||
# password must have at least three bytes that are not present in the
|
||||
# old password
|
||||
#
|
||||
password required pam_cracklib.so \
|
||||
difok=3 minlen=15 dcredit= 2 ocredit=2
|
||||
password required pam_pwdb.so use_authtok nullok md5
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,179 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_deny.sgml,v 1.3 1997/02/15 18:25:44 morgan Exp morgan $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The locking-out module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
pam_deny
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
current <bf/Linux-PAM/ maintainer
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
account; authentication; password; session
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
clean.
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module can be used to deny access. It always indicates a failure
|
||||
to the application through the PAM framework. As is commented in the
|
||||
overview section <ref id="overview-section" name="above">, this module
|
||||
might be suitable for using for default (the <tt/OTHER/) entries.
|
||||
|
||||
<sect2>Account component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This component does nothing other than return a failure. The
|
||||
failure type is <tt/PAM_ACCT_EXPIRED/.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
Stacking this module with type <tt/account/ will prevent the user from
|
||||
gaining access to the system via applications that refer to
|
||||
<bf/Linux-PAM/'s account management function <tt/pam_acct_mgmt()/.
|
||||
|
||||
<p>
|
||||
The following example would make it impossible to login:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# add this line to your other login entries to disable all accounts
|
||||
#
|
||||
login account required pam_deny.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This component does nothing other than return a failure. The failure
|
||||
type is <tt/PAM_AUTH_ERR/ in the case that <tt/pam_authenticate()/ is
|
||||
called (when the application tries to authenticate the user), and is
|
||||
<tt/PAM_CRED_UNAVAIL/ when the application calls <tt/pam_setcred()/
|
||||
(to establish and set the credentials of the user -- it is unlikely
|
||||
that this function will ever be called in practice).
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
To deny access to default applications with this component of the
|
||||
<tt/pam_deny/ module, you might include the following line in your
|
||||
<bf/Linux-PAM/ configuration file:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# add this line to your existing OTHER entries to prevent
|
||||
# authentication succeeding with default applications.
|
||||
#
|
||||
OTHER auth required pam_deny.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Password component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This component of the module denies the user the opportunity to change
|
||||
their password. It always responds with <tt/PAM_AUTHTOK_ERR/ when
|
||||
invoked.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
This module should be used to prevent an application from updating the
|
||||
applicant user's password. For example, to prevent <tt/login/ from
|
||||
automatically prompting for a new password when the old one has
|
||||
expired you should include the following line in your configuration
|
||||
file:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# add this line to your other login entries to prevent the login
|
||||
# application from being able to change the user's password.
|
||||
#
|
||||
login password required pam_deny.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Session component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This aspect of the module prevents an application from starting a
|
||||
session on the host computer.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
Together with another session module, that displays a message of the
|
||||
day perhaps (XXX - such a module needs to be written),
|
||||
this module can be used to block a user from starting a shell. Given
|
||||
the presence of a <tt/pam_motd/ module, we might use the following
|
||||
entries in the configuration file to inform the user it is system
|
||||
time:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# An example to see how to configure login to refuse the user a
|
||||
# session (politely)
|
||||
#
|
||||
login session required pam_motd.so \
|
||||
file=/etc/system_time
|
||||
login session required pam_deny.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,125 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_env.sgml,v 1.1 1997/04/05 06:50:42 morgan Exp $
|
||||
|
||||
This file was written by Dave Kinchlea <kinch@kinch.ark.com>
|
||||
Ed. AGM
|
||||
-->
|
||||
|
||||
<sect1>Set/unset environment variables
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_env/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Dave Kinchlea <kinch@kinch.ark.com>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
Authentication (setcred)
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
<tt>/etc/security/pam_env.conf</tt>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module allows the (un)setting of environment variables. Supported
|
||||
is the use of previously set environment variables as well as
|
||||
<em>PAM_ITEM</em>s such as <tt>PAM_RHOST</tt>.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/; <tt/conffile=/<em/configuration-file-name/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
This module allows you to (un)set arbitrary environment variables
|
||||
using fixed strings, the value of previously set environment variables
|
||||
and/or <em/PAM_ITEM/s.
|
||||
|
||||
<p>
|
||||
All is controlled via a configuration file (by default,
|
||||
<tt>/etc/security/pam_env.conf</tt> but can be overriden with
|
||||
<tt>connfile</tt> argument). Each line starts with the variable name,
|
||||
there are then two possible options for each variable <bf>DEFAULT</bf>
|
||||
and <bf>OVERRIDE</bf>. <bf>DEFAULT</bf> allows and administrator to
|
||||
set the value of the variable to some default value, if none is
|
||||
supplied then the empty string is assumed. The <bf>OVERRIDE</bf>
|
||||
option tells pam_env that it should enter in its value (overriding the
|
||||
default value) if there is one to use. <bf>OVERRIDE</bf> is not used,
|
||||
<tt>""</tt> is assumed and no override will be done.
|
||||
|
||||
<p>
|
||||
<tscreen>
|
||||
<verb>
|
||||
VARIABLE [DEFAULT=[value]] [OVERRIDE=[value]]
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
<p>
|
||||
(Possibly non-existent) environment variables may be used in values
|
||||
using the <tt>${string}</tt> syntax and (possibly
|
||||
non-existent) <em/PAM_ITEM/s may be used in values using the
|
||||
<tt>@{string}</tt> syntax. Both the <tt>$</tt>
|
||||
and <tt>@</tt> characters can be backslash-escaped to be used
|
||||
as literal values (as in <tt>\$</tt>. Double quotes may
|
||||
be used in values (but not environment variable names) when white
|
||||
space is needed <bf>the full value must be delimited by the quotes and
|
||||
embedded or escaped quotes are not supported</bf>.
|
||||
|
||||
<p>
|
||||
The behavior of this module can be modified with one of the following
|
||||
flags:
|
||||
|
||||
<p>
|
||||
<itemize>
|
||||
|
||||
<item><tt/debug/
|
||||
- write more information to <tt/syslog(3)/.
|
||||
|
||||
<item><tt/conffile=/<em/filename/
|
||||
- by default the file <tt>/etc/security/pam_env.conf</tt> is used as
|
||||
the configuration file. This option overrides the default. You must
|
||||
supply a complete path + file name.
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
See sample <tt>pam_env.conf</tt> for more information and examples.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,150 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_filter.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The filter module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
|
||||
pam_filter
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
|
||||
account; authentication; password; session
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
Not yet.
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
This module compiles cleanly on Linux based systems.
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
To function it requires <em/filters/ to be installed on the system.
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module was written to offer a plug-in alternative to programs
|
||||
like ttysnoop (XXX - need a reference). Since writing a filter that
|
||||
performs this function has not occurred, it is currently only a toy.
|
||||
The single filter provided with the module simply transposes upper and
|
||||
lower case letters in the input and output streams. (This can be very
|
||||
annoying and is not kind to termcap based editors).
|
||||
|
||||
<sect2>Account+Authentication+Password+Session components
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tt/debug/; <tt/new_term/; <tt/non_term/; <tt/runX/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
Each component of the module has the potential to invoke the desired
|
||||
filter. The filter is always <tt/execv(2)/d with the privilege of the
|
||||
calling application and <bf/not/ that of the user. For this reason it
|
||||
cannot usually be killed by the user without closing their session.
|
||||
|
||||
<p>
|
||||
The behavior of the module can be significantly altered by the
|
||||
arguments passed to it in the <bf/Linux-PAM/ configuration file:
|
||||
<itemize>
|
||||
<item><tt/debug/ -
|
||||
|
||||
this option increases the amount of information logged to
|
||||
<tt/syslog(3)/ as the module is executed.
|
||||
|
||||
<item><tt/new_term/ -
|
||||
|
||||
the default action of the filter is to set the <tt/PAM_TTY/ item to
|
||||
indicate the terminal that the user is using to connect to the
|
||||
application. This argument indicates that the filter should set
|
||||
<tt/PAM_TTY/ to the filtered pseudo-terminal.
|
||||
|
||||
<item><tt/non_term/ -
|
||||
don't try to set the <tt/PAM_TTY/ item.
|
||||
|
||||
<item><tt/runX/ -
|
||||
|
||||
in order that the module can invoke a filter it should know when to
|
||||
invoke it. This argument is required to tell the filter when to do
|
||||
this. The arguments that follow this one are respectively the full
|
||||
pathname of the filter to be run and any command line arguments that
|
||||
the filter might expect.
|
||||
|
||||
<p>
|
||||
Permitted values for <tt/X/ are <tt/1/ and <tt/2/. These indicate the
|
||||
precise time the that filter is to be run. To explain this concept it
|
||||
will be useful to have read the Linux-PAM Module developer's
|
||||
guide. Basically, for each management group there are up to two ways
|
||||
of calling the module's functions.
|
||||
|
||||
In the case of the <em/authentication/ and <em/session/ components
|
||||
there are actually two separate functions. For the case of
|
||||
authentication, these functions are <tt/_authenticate/ and
|
||||
<tt/_setcred/ -- here <tt/run1/ means run the filter from the
|
||||
<tt/_authenticate/ function and <tt/run2/ means run the filter from
|
||||
<tt/_setcred/. In the case of the session modules, <tt/run1/ implies
|
||||
that the filter is invoked at the <tt/_open_session/ stage, and
|
||||
<tt/run2/ for <tt/_close_session/.
|
||||
|
||||
<p>
|
||||
For the case of the account component. Either <tt/run1/ or <tt/run2/
|
||||
may be used.
|
||||
|
||||
<p>
|
||||
For the case of the password component, <tt/run1/ is used to indicate
|
||||
that the filter is run on the first occasion <tt/_chauthtok/ is run
|
||||
(the <tt/PAM_PRELIM_CHECK/ phase) and <tt/run2/ is used to indicate
|
||||
that the filter is run on the second occasion (the
|
||||
<tt/PAM_UPDATE_AUTHTOK/ phase).
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
At the time of writing there is little real use to be made of this
|
||||
module. For fun you might try adding the following line to your
|
||||
login's configuration entries
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# An example to see how to configure login to transpose upper and
|
||||
# lower case letters once the user has logged in(!)
|
||||
#
|
||||
login session required pam_filter.so \
|
||||
run1 /usr/sbin/pam_filter/upperLOWER
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,93 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_ftp.sgml,v 1.1 1996/11/30 20:59:32 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>Anonymous access module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_ftp.so/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
prompts for email address of user; easily spoofed (XXX - needs work)
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
The purpose of this module is to provide a pluggable anonymous ftp
|
||||
mode of access.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/;
|
||||
<tt/users=XXX,YYY,.../;
|
||||
<tt/ignore/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This module intercepts the user's name and password. If the name is
|
||||
``<tt/ftp/'' or ``<tt/anonymous/'', the user's password is broken up
|
||||
at the `<tt/@/' delimiter into a <tt/PAM_RUSER/ and a <tt/PAM_RHOST/
|
||||
part; these pam-items being set accordingly. The username is set to
|
||||
``<tt/ftp/''. In this case the module succeeds. Alternatively, the
|
||||
module sets the <tt/PAM_AUTHTOK/ item with the entered password and
|
||||
fails.
|
||||
|
||||
<p>
|
||||
The behavior of the module can be modified with the following flags:
|
||||
<itemize>
|
||||
<item><tt/debug/ -
|
||||
log more information to with <tt/syslog(3)/.
|
||||
|
||||
<item><tt/users=XXX,YYY,.../ -
|
||||
instead of ``<tt/ftp/'' or ``<tt/anonymous/'', provide anonymous login
|
||||
to the comma separated list of users; ``<tt/XXX,YYY,.../''. Should the
|
||||
applicant enter one of these usernames the returned username is set to
|
||||
the first in the list; ``<tt/XXX/''.
|
||||
|
||||
<item><tt/ignore/ -
|
||||
pay no attention to the email address of the user (if supplied).
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
An example of the use of this module is provided in the configuration
|
||||
file section <ref id="configuration" name="above">. With care, this
|
||||
module could be used to provide new/temporary account anonymous
|
||||
login.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,108 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_group.sgml,v 1.2 1997/01/04 20:50:10 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The group access module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_group/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
Sensitive to <em/setgid/ status of file-systems accessible to users.
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
Requires an <tt>/etc/security/group.conf</tt> file. Can be compiled
|
||||
with or without <tt/libpwdb/.
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
Only through correctly set <tt/PAM_TTY/ item.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module provides group-settings based on the user's name and the
|
||||
terminal they are requesting a given service from. It takes note of
|
||||
the time of day.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This module does not authenticate the user, but instead it grants
|
||||
group memberships (in the credential setting phase of the
|
||||
authentication module) to the user. Such memberships are based on the
|
||||
service they are applying for. The group memberships are listed in
|
||||
text form in the <tt>/etc/security/group.conf</tt> file.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
For this module to function correctly there must be a correctly
|
||||
formatted <tt>/etc/security/groups.conf</tt> file present. The format
|
||||
of this file is as follows. Group memberships are given based on the
|
||||
service application satisfying any combination of lines in the
|
||||
configuration file. Each line (barring comments which are preceded by
|
||||
`<tt/#/' marks) has the following
|
||||
syntax:
|
||||
<tscreen>
|
||||
<verb>
|
||||
services ; ttys ; users ; times ; groups
|
||||
</verb>
|
||||
</tscreen>
|
||||
Here the first four fields share the syntax of the <tt>pam_time</tt>
|
||||
configuration file; <tt>/etc/security/pam_time.conf</tt>, and the last
|
||||
field, the <tt/groups/ field, is a comma (or space) separated list of
|
||||
the text-names of a selection of groups. If the users application for
|
||||
service satisfies the first four fields, the user is granted membership
|
||||
of the listed groups.
|
||||
|
||||
<p>
|
||||
As stated in above this module's usefulness relies on the file-systems
|
||||
accessible to the user. The point being that once granted the
|
||||
membership of a group, the user may attempt to create a <em/setgid/
|
||||
binary with a restricted group ownership. Later, when the user is not
|
||||
given membership to this group, they can recover group membership with
|
||||
the precompiled binary. The reason that the file-systems that the user
|
||||
has access to are so significant, is the fact that when a system is
|
||||
mounted <em/nosuid/ the user is unable to create or execute such a
|
||||
binary file. For this module to provide any level of security, all
|
||||
file-systems that the user has write access to should be mounted
|
||||
<em/nosuid/.
|
||||
|
||||
<p>
|
||||
The <tt>pam_group</tt> module fuctions in parallel with the
|
||||
<tt>/etc/group</tt> file. If the user is granted any groups based on
|
||||
the behavior of this module, they are granted <em>in addition</em> to
|
||||
those entries <tt>/etc/group</tt> (or equivalent).
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,126 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_krb4.sgml,v 1.1 1996/11/30 20:59:32 morgan Exp $
|
||||
|
||||
This file was written by Derrick J. Brashear <shadow@DEMENTIA.ORG>
|
||||
-->
|
||||
|
||||
<sect1>The Kerberos 4 module.
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_krb4/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Derrick J. Brashear <shadow@dementia.org>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication; password; session
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
uses API
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
libraries - <tt/libkrb/, <tt/libdes/, <tt/libcom_err/, <tt/libkadm/;
|
||||
and a set of Kerberos include files.
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
Gets Kerberos ticket granting ticket via a Kerberos key distribution
|
||||
center reached via the network.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module provides an interface for doing Kerberos verification of a
|
||||
user's password, getting the user a Kerberos ticket granting ticket
|
||||
for use with the Kerberos ticket granting service, destroying the
|
||||
user's tickets at logout time, and changing a Kerberos password.
|
||||
|
||||
<sect2> Session component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This component of the module currently sets the user's <tt/KRBTKFILE/
|
||||
environment variable (although there is currently no way to export
|
||||
this), as well as deleting the user's ticket file upon logout (until
|
||||
<tt/PAM_CRED_DELETE/ is supported by <em/login/).
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
This part of the module won't be terribly useful until we can change
|
||||
the environment from within a <tt/Linux-PAM/ module.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2> Password component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/use_first_pass/; <tt/try_first_pass/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This component of the module changes a user's Kerberos password
|
||||
by first getting and using the user's old password to get
|
||||
a session key for the password changing service, then sending
|
||||
a new password to that service.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
This should only be used with a real Kerberos v4 <tt/kadmind/. It
|
||||
cannot be used with an AFS kaserver unless special provisions are
|
||||
made. Contact the module author for more information.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2> Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/use_first_pass/; <tt/try_first_pass/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This component of the module verifies a user's Kerberos password
|
||||
by requesting a ticket granting ticket from the Kerberos server
|
||||
and optionally using it to attempt to retrieve the local computer's
|
||||
host key and verifying using the key file on the local machine if
|
||||
one exists.
|
||||
|
||||
It also writes out a ticket file for the user to use later, and
|
||||
deletes the ticket file upon logout (not until <tt/PAM_CRED_DELETE/
|
||||
is called from <em/login/).
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
This module can be used with a real Kerberos server using MIT
|
||||
v4 Kerberos keys. The module or the system Kerberos libraries
|
||||
may be modified to support AFS style Kerberos keys. Currently
|
||||
this is not supported to avoid cryptography constraints.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,119 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_mail.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The last login module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_lastlog/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
auth
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
uses information contained in the <tt>/var/log/wtmp</tt> file.
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This session module maintains the <tt>/var/log/wtmp</tt> file. Adding
|
||||
an open entry when called via the <tt>pam_open_seesion()</tt> function
|
||||
and completing it when <tt>pam_close_session()</tt> is called. This
|
||||
module can also display a line of information about the last login of
|
||||
the user. If an application already performs these tasks, it is not
|
||||
necessary to use this module.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/; <tt/nodate/; <tt/noterm/; <tt/nohost/; <tt/silent/;
|
||||
<tt/never/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
<p>
|
||||
This module can be used to provide a ``Last login on ...''
|
||||
message. when the user logs into the system from what ever application
|
||||
uses the PAM libraries. In addition, the module maintains the
|
||||
<tt>/var/log/wtmp</tt> file.
|
||||
|
||||
<p>
|
||||
The behavior of this module can be modified with one of the following
|
||||
flags:
|
||||
|
||||
<p>
|
||||
<itemize>
|
||||
<item><tt/debug/
|
||||
- write more information to <tt/syslog(3)/.
|
||||
|
||||
<item><tt/nodate/
|
||||
- neglect to give the date of the last login when displaying
|
||||
information about the last login on the system.
|
||||
|
||||
<item><tt/noterm/
|
||||
- neglect to diplay the terminal name on which the last login was
|
||||
attempt.
|
||||
|
||||
<item><tt/nohost/
|
||||
- neglect to indicate from which host the last login was attempted.
|
||||
|
||||
<item><tt/silent/
|
||||
- neglect to inform the user about any previous login: just update
|
||||
the <tt>/var/log/wtmp</tt> file.
|
||||
|
||||
<item><tt/never/
|
||||
- if the <tt>/var/log/wtmp</tt> file does not contain any old entries
|
||||
for the user, indicate that the user has never previously logged in
|
||||
with a ``welcome..." message.
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
This module can be used to indicate that the user has new mail when
|
||||
they <em/login/ to the system. Here is a sample entry for your
|
||||
<tt>/etc/pam.conf</tt> file:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# do we have any mail?
|
||||
#
|
||||
login session optional pam_lastlog.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
<p>
|
||||
Note, some applications may perform this function themselves. In such
|
||||
cases, this module is not necessary.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,196 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_limits.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
from information compiled by Cristian Gafton (author of module)
|
||||
-->
|
||||
|
||||
<sect1>The resource limits module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_limits/
|
||||
|
||||
<tag><bf>Authors:</bf></tag>
|
||||
Cristian Gafton <gafton@redhat.com> <newline>
|
||||
Thanks are also due to Elliot Lee <sopwith@redhat.com>
|
||||
for his comments on improving this module.
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Cristian Gafton - 1996/11/20
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
session
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
requires an <tt>/etc/security/limits.conf</tt> file and kernel support
|
||||
for resource limits. Also uses the library, <tt/libpwdb/.
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module, through the <bf/Linux-PAM/ <em/open/-session hook, sets
|
||||
limits on the system resources that can be obtained in a
|
||||
user-session. Its actions are dictated more explicitly through the
|
||||
configuration file discussed below.
|
||||
|
||||
<sect2>Session component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/; <tt>conf=/path/to/file.conf</tt>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
Through the contents of the configuration file,
|
||||
<tt>/etc/security/limits.conf</tt>, resource limits are placed on
|
||||
users' sessions. Users of <tt/uid=0/ are not affected by this
|
||||
restriction.
|
||||
|
||||
<p>
|
||||
The behavior of this module can be modified with the following
|
||||
arguments:
|
||||
<itemize>
|
||||
|
||||
<item><tt/debug/ -
|
||||
verbose logging to <tt/syslog(3)/.
|
||||
|
||||
<item><tt>conf=/path/to/file.conf</tt> -
|
||||
indicate an alternative <em/limits/ configuration file to the default.
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
In order to use this module the system administrator must first create
|
||||
a <em/root-only-readable/ file (default is
|
||||
<tt>/etc/security/limits.conf</tt>). This file describes the resource
|
||||
limits the superuser wishes to impose on users and groups. No limits
|
||||
are imposed on <tt/uid=0/ accounts.
|
||||
|
||||
<p>
|
||||
Each line of the configuration file describes a limit for a user in
|
||||
the form:
|
||||
<tscreen>
|
||||
<verb>
|
||||
<domain> <type> <item> <value>
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
<p>
|
||||
The fields listed above should be filled as follows...<newline>
|
||||
<tt><domain></tt> can be:
|
||||
<itemize>
|
||||
<item> a username
|
||||
<item> a groupname, with <tt>@group</tt> syntax
|
||||
<item> the wild-card <tt/*/, for default entry
|
||||
</itemize>
|
||||
|
||||
<p>
|
||||
<tt><type></tt> can have the two values:
|
||||
<itemize>
|
||||
|
||||
<item> <tt/hard/ for enforcing <em/hard/ resource limits. These limits
|
||||
are set by the superuser and enforced by the Linux Kernel. The user
|
||||
cannot raise his requirement of system resources above such values.
|
||||
|
||||
<item> <tt/soft/ for enforcing <em/soft/ resource limits. These limits
|
||||
are ones that the user can move up or down within the permitted range
|
||||
by any pre-exisiting <em/hard/ limits. The values specified with this
|
||||
token can be thought of as <em/default/ values, for normal system
|
||||
usage.
|
||||
|
||||
</itemize>
|
||||
|
||||
<p>
|
||||
<tt><item></tt> can be one of the following:
|
||||
<itemize>
|
||||
<item><tt/core/ - limits the core file size (KB)
|
||||
<item><tt/data/ - max data size (KB)
|
||||
<item><tt/fsize/ - maximum filesize (KB)
|
||||
<item><tt/memlock/ - max locked-in-memory address space (KB)
|
||||
<item><tt/nofile/ - max number of open files
|
||||
<item><tt/rss/ - max resident set size (KB)
|
||||
<item><tt/stack/ - max stack size (KB)
|
||||
<item><tt/cpu/ - max CPU time (MIN)
|
||||
<item><tt/nproc/ - max number of processes
|
||||
<item><tt/as/ - address space limit
|
||||
<item><tt/maxlogins/ - max number of logins for this user.
|
||||
</itemize>
|
||||
|
||||
<p>
|
||||
To completely disable limits for a user (or a group), a single dash
|
||||
(-) will do (Example: ``<tt/bin -/'', ``<tt/@admin -/''). Please
|
||||
remember that individual limits have priority over group limits, so if
|
||||
you impose no limits for <tt/admin/ group, but one of the members in this
|
||||
group have a limits line, the user will have its limits set according
|
||||
to this line.
|
||||
|
||||
<p>
|
||||
Also, please note that all limit settings are set <em/per login/.
|
||||
They are not global, nor are they permanent; existing only for the
|
||||
duration of the session.
|
||||
|
||||
<p>
|
||||
In the <em/limits/ configuration file, the ``<tt/#/'' character
|
||||
introduces a comment - after which the rest of the line is ignored.
|
||||
|
||||
<p>
|
||||
The <tt/pam_limits/ module does its best to report configuration
|
||||
problems found in its configuration file via <tt/syslog(3)/.
|
||||
|
||||
<p>
|
||||
The following is an example configuration file:
|
||||
<tscreen>
|
||||
<verb>
|
||||
# EXAMPLE /etc/security/limits.conf file:
|
||||
# =======================================
|
||||
# <domain> <type> <item> <value>
|
||||
* soft core 0
|
||||
* hard rss 10000
|
||||
@student hard nproc 20
|
||||
@faculty soft nproc 20
|
||||
@faculty hard nproc 50
|
||||
ftp hard nproc 0
|
||||
@student - maxlogins 4
|
||||
</verb>
|
||||
</tscreen>
|
||||
Note, the use of <tt/soft/ and <tt/hard/ limits for the same resource
|
||||
(see <tt/@faculty/) -- this establishes the <em/default/ and permitted
|
||||
<em/extreme/ level of resources that the user can can obtain in a
|
||||
given service-session.
|
||||
|
||||
<p>
|
||||
For the services that need resources limits (login for example) put a
|
||||
the following line in <tt>/etc/pam.conf</tt> as the last line for that
|
||||
service (usually after the pam_unix session line:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# Resource limits imposed on login sessions via pam_limits
|
||||
#
|
||||
login session required pam_limits.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,138 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_listfile.sgml,v 1.3 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Michael K. Johnson <johnsonm@redhat.com>
|
||||
-->
|
||||
|
||||
<sect1>The list-file module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_listfile/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Elliot Lee <tt><sopwith@cuc.edu></tt>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Red Hat Software:<newline>
|
||||
Michael K. Johnson <johnsonm@redhat.com> 1996/11/18<newline>
|
||||
(if unavailable, contact Elliot Lee <sopwith@cuc.edu>).
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
clean
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
The list-file module provides a way to deny or allow services based on
|
||||
an arbitrary file.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tt>onerr=succeed|fail</tt>;
|
||||
<tt>sense=allow|deny</tt>;
|
||||
<tt>file=</tt><it>filename</it>;
|
||||
<tt>item=user|tty|rhost|ruser|group|shell</tt>
|
||||
<tt>apply=user|@group</tt>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
The module gets the item of the type specified -- <tt>user</tt> specifies
|
||||
the username, <tt>PAM_USER</tt>; tty specifies the name of the terminal
|
||||
over which the request has been made, <tt>PAM_TTY</tt>; rhost specifies
|
||||
the name of the remote host (if any) from which the request was made,
|
||||
<tt>PAM_RHOST</tt>; and ruser specifies the name of the remote user
|
||||
(if available) who made the request, <tt>PAM_RUSER</tt> -- and looks for
|
||||
an instance of that item in the file <it>filename</it>. <it>filename</it>
|
||||
contains one line per item listed. If the item is found, then if
|
||||
<tt>sense=allow</tt>, <tt>PAM_SUCCESS</tt> is returned, causing the
|
||||
authorization request to succeed; else if <tt>sense=deny</tt>,
|
||||
<tt>PAM_AUTH_ERR</tt> is returned, causing the authorization
|
||||
request to fail.
|
||||
|
||||
<p>
|
||||
If an error is encountered (for instance, if <it>filename</it>
|
||||
does not exist, or a poorly-constructed argument is encountered),
|
||||
then if <tt>onerr=succeed</tt>, <tt>PAM_SUCCESS</tt> is returned,
|
||||
otherwise if <tt>onerr=fail</tt>, <tt>PAM_AUTH_ERR</tt> or
|
||||
<tt>PAM_SERVICE_ERR</tt> (as appropriate) will be returned.
|
||||
|
||||
<p>
|
||||
An additional argument, <tt>apply=</tt>, can be used to restrict the
|
||||
application of the above to a specific user
|
||||
(<tt>apply=</tt><em>username</em>) or a given group
|
||||
(<tt>apply=@</tt><em>groupname</em>). This added restriction is only
|
||||
meaningful when used with the <tt/tty/, <tt/rhost/ and <tt/shell/
|
||||
<em/items/.
|
||||
|
||||
<p>
|
||||
Besides this last one, all arguments should be specified; do not count
|
||||
on any default behavior, as it is subject to change.
|
||||
|
||||
<p>
|
||||
No credentials are awarded by this module.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
Classic ``ftpusers'' authentication can be implemented with this entry
|
||||
in <tt>/etc/pam.conf</tt>:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# deny ftp-access to users listed in the /etc/ftpusers file
|
||||
#
|
||||
ftp auth required pam_listfile.so \
|
||||
onerr=succeed item=user sense=deny file=/etc/ftpusers
|
||||
</verb>
|
||||
</tscreen>
|
||||
Note, users listed in <tt>/etc/ftpusers</tt> file are
|
||||
(counterintuitively) <bf/not/ allowed access to the ftp service.
|
||||
|
||||
<p>
|
||||
To allow login access only for certain users, you can use an
|
||||
pam.conf entry like this:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# permit login to users listed in /etc/loginusers
|
||||
#
|
||||
login auth required pam_listfile.so \
|
||||
onerr=fail item=user sense=allow file=/etc/loginusers
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
<p>
|
||||
For this example to work, all users who are allowed to use the login
|
||||
service should be listed in the file <tt>/etc/loginusers</tt>. Unless
|
||||
you are explicitly trying to lock out root, make sure that when you do
|
||||
this, you leave a way for root to log in, either by listing root in
|
||||
<tt>/etc/loginusers</tt>, or by listing a user who is able to <em/su/
|
||||
to the root account.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,124 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_mail.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The mail module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_mail/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
auth
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
Default mail directory <tt>/var/spool/mail/</tt>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module looks at the user's mail directory and indicates
|
||||
whether the user has any mail in it.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/; <tt/dir=/<em/direcory-name/; <tt/nopen/; <tt/close/;
|
||||
<tt/noenv/; <tt/empty/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This module provides the ``you have new mail'' service to the user. It
|
||||
can be plugged into any application that has credential hooks. It gives a
|
||||
single message indicating the <em/newness/ of any mail it finds in the
|
||||
user's mail folder. This module also sets the <bf/Linux-PAM/
|
||||
environment variable, <tt/MAIL/, to the user's mail directory.
|
||||
|
||||
<p>
|
||||
Although the module supplies functions for the authentication
|
||||
management group of functions, it cannot be used to authenticate a
|
||||
user; its authentication function instructs <tt/libpam/ to simply
|
||||
ignore it when authenticating the user.
|
||||
|
||||
<p>
|
||||
The behavior of this module can be modified with one of the following
|
||||
flags:
|
||||
|
||||
<p>
|
||||
<itemize>
|
||||
<item><tt/debug/
|
||||
- write more information to <tt/syslog(3)/.
|
||||
|
||||
<item><tt/dir=/<em/pathname/
|
||||
- look for the users' mail in an alternative directory given by
|
||||
<em/pathname/. The default location for mail is
|
||||
<tt>/var/spool/mail</tt>. Note, if the supplied <em/pathname/ is
|
||||
prefixed by a `<tt/˜/', the directory is interpreted as
|
||||
indicating a file in the user's home directory.
|
||||
|
||||
<item><tt/nopen/
|
||||
- instruct the module to <em/not/ print any mail information when the
|
||||
user's credentials are acquired. This flag is useful to get the <tt/MAIL/
|
||||
environment variable set, but to not display any information about it.
|
||||
|
||||
<item><tt/close/
|
||||
- instruct the module to indicate if the user has any mail at the as
|
||||
the user's credentials are revoked.
|
||||
|
||||
<item><tt/noenv/
|
||||
- do not set the <tt/MAIL/ environment variable.
|
||||
|
||||
<item><tt/empty/
|
||||
- indicate that the user's mail directory is empty if this is found to
|
||||
be the case.
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
This module can be used to indicate that the user has new mail when
|
||||
they <em/login/ to the system. Here is a sample entry for your
|
||||
<tt>/etc/pam.conf</tt> file:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# do we have any mail?
|
||||
#
|
||||
login auth optional pam_mail.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
<p>
|
||||
Note, some applications may perform this function themselves. In such
|
||||
cases, this module is not necessary.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,75 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_nologin.sgml,v 1.2 1997/01/04 21:56:55 morgan Exp $
|
||||
|
||||
This file was written by Michael K. Johnson <johnsonm@redhat.com>
|
||||
-->
|
||||
|
||||
<sect1>The no-login module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_nologin/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Written by Michael K. Johnson <johnsonm@redhat.com><newline>
|
||||
(based on code taken from a module written by Andrew G. Morgan
|
||||
<morgan@parc.power.net>).
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Michael K. Johnson <johnsonm@redhat.com>
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
1 warning about dropping const
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
Provides standard Unix <em/nologin/ authentication.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
Provides standard Unix <em/nologin/ authentication. If the file
|
||||
<tt>/etc/nologin</tt> exists, only root is allowed to log in; other
|
||||
users are turned away with an error message. All users (root or
|
||||
otherwise) are shown the contents of <tt>/etc/nologin</tt>.
|
||||
|
||||
<p>
|
||||
If the file <tt>/etc/nologin</tt> does not exist, this module succeeds
|
||||
silently.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
In order to make this module effective, all login methods should
|
||||
be secured by it. It should be used as a <tt>required</tt>
|
||||
method listed before any <tt>sufficient</tt> methods in order to
|
||||
get standard Unix nologin semantics.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,83 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_permit.sgml,v 1.2 1997/02/15 18:20:12 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The promiscuous module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
pam_permit
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan, <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Linux-PAM maintainer.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
account; authentication; password; session
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
VERY LOW. Use with extreme caution.
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
Clean.
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module is very dangerous. It should be used with extreme
|
||||
caution. Its action is always to permit access. It does nothing else.
|
||||
|
||||
<sect2>Account+Authentication+Password+Session components
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
No matter what management group, the action of this module is to
|
||||
simply return <tt/PAM_SUCCESS/ -- operation successful.
|
||||
|
||||
<p>
|
||||
In the case of authentication, the user's name will be acquired. Many
|
||||
applications become confused if this name is unknown.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
It is seldom a good idea to use this module. However, it does have
|
||||
some legitimate uses. For example, if the system-administrator wishes
|
||||
to turn off the account management on a workstation, and at the same
|
||||
time continue to allow logins, then she might use the following
|
||||
configuration file entry for login:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# add this line to your other login entries to disable account
|
||||
# management, but continue to permit users to log in...
|
||||
#
|
||||
login account required pam_permit.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,245 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_pwdb.sgml,v 1.3 1997/04/05 06:50:42 morgan Exp morgan $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The Password-Database module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
pam_pwdb
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Cristian Gafton <gafton@redhat.com> <newline>
|
||||
and Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Authors.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
account; authentication; password; session
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
Requires properly configured <tt/libpwdb/
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module is a pluggable replacement for the <tt/pam_unix_../
|
||||
modules. It uses the generic interface of the <em/Password Database/
|
||||
library
|
||||
<tt><htmlurl
|
||||
url="http://parc.power.net/morgan/libpwdb/index.html"
|
||||
name="http://parc.power.net/morgan/libpwdb/index.html"></tt>.
|
||||
|
||||
<sect2>Account component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
The <tt/debug/ argument makes the accounting functions of this module
|
||||
<tt/syslog(3)/ more information on its actions. (Remaining arguments
|
||||
supported by the other functions of this module are silently ignored,
|
||||
but others are logged as errors through <tt/syslog(3)/).
|
||||
|
||||
Based on the following <tt/pwdb_element/s:
|
||||
<tt/expire/;
|
||||
<tt/last_change/;
|
||||
<tt/max_change/;
|
||||
<tt/defer_change/;
|
||||
<tt/warn_change/,
|
||||
this module performs the task of establishing the status of the user's
|
||||
account and password. In the case of the latter, it may offer advice
|
||||
to the user on changing their password or, through the
|
||||
<tt/PAM_AUTHTOKEN_REQD/ return, delay giving service to the user until
|
||||
they have established a new password. The entries listed above are
|
||||
documented in the <em/Password Database Library Guide/ (see pointer
|
||||
above). Should the user's record not contain one or more of these
|
||||
entries, the corresponding <em/shadow/ check is not performed.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
In its accounting mode, this module can be inserted as follows:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# Ensure users account and password are still active
|
||||
#
|
||||
login account required pam_pwdb.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/;
|
||||
<tt/use_first_pass/;
|
||||
<tt/try_first_pass/;
|
||||
<tt/nullok/;
|
||||
<tt/nodelay/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
The <tt/debug/ argument makes the authentication functions of this
|
||||
module <tt/syslog(3)/ more information on its actions.
|
||||
|
||||
<p>
|
||||
The default action of this module is to not permit the user access to
|
||||
a service if their <em/official/ password is blank. The <tt/nullok/
|
||||
argument overrides this default.
|
||||
|
||||
<p>
|
||||
When given the argument <tt/try_first_pass/, before prompting the user
|
||||
for their password, the module first tries the previous stacked
|
||||
<tt/auth/-module's password in case that satisfies this module as
|
||||
well. The argument <tt/use_first_pass/ forces the module to use such a
|
||||
recalled password and will never prompt the user - if no password is
|
||||
available or the password is not appropriate, the user will be denied
|
||||
access.
|
||||
|
||||
<p>
|
||||
The argument, <tt>nodelay</tt>, can be used to discourage the
|
||||
authentication component from requesting a delay should the
|
||||
authentication as a whole fail. The default action is for the module
|
||||
to request a delay-on-failure of the order of one second.
|
||||
|
||||
<p>
|
||||
Remaining arguments, supported by the other functions of this module,
|
||||
are silently ignored. Other arguments are logged as errors through
|
||||
<tt/syslog(3)/.
|
||||
|
||||
<p>
|
||||
A helper binary, <tt>pwdb_chkpwd</tt>, is provided to check the user's
|
||||
password when it is stored in a read protected database. This binary
|
||||
is very simple and will only check the password of the user invoking
|
||||
it. It is called transparently on behalf of the user by the
|
||||
authenticating component of this module. In this way it is possible
|
||||
for applications like <em>xlock</em> to work without being setuid-root.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
The correct functionality of this module is dictated by having an
|
||||
appropriate <tt>/etc/pwdb.conf</tt> file, the user
|
||||
databases specified there dictate the source of the authenticated
|
||||
user's record.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Password component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/; <tt/nullok/; <tt/not_set_pass/; <tt/use_authtok/;
|
||||
<tt/try_first_pass/; <tt/use_first_pass/; <tt/md5/; <tt/bigcrypt/;
|
||||
<tt/shadow/; <tt/radius/; <tt/unix/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This part of the <tt/pam_pwdb/ module performs the task of updating
|
||||
the user's password. Thanks to the flexibility of <tt/libpwdb/ this
|
||||
module is able to move the user's password from one database to
|
||||
another, perhaps securing the user's database entry in a dynamic
|
||||
manner (<em/this is very ALPHA code at the moment!/) - this is the
|
||||
purpose of the <tt/shadow/, <tt/radius/ and <tt/unix/ arguments.
|
||||
|
||||
<p>
|
||||
In the case of conventional unix databases (which store the password
|
||||
encrypted) the <tt/md5/ argument is used to do the encryption with the
|
||||
MD5 function as opposed to the <em/conventional/ <tt/crypt(3)/ call.
|
||||
As an alternative to this, the <tt/bigcrypt/ argument can be used to
|
||||
encrypt more than the first 8 characters of a password with DEC's
|
||||
(Digital Equipment Cooperation) `C2' extension to the standard UNIX
|
||||
<tt/crypt()/ algorithm.
|
||||
|
||||
<p>
|
||||
The <tt/nullok/ module is used to permit the changing of a password
|
||||
<em/from/ an empty one. Without this argument, empty passwords are
|
||||
treated as account-locking ones.
|
||||
|
||||
<p>
|
||||
The argument <tt/use_first_pass/ is used to lock the choice of old and
|
||||
new passwords to that dictated by the previously stacked <tt/password/
|
||||
module. The <tt/try_first_pass/ argument is used to avoid the user
|
||||
having to re-enter an old password when <tt/pam_pwdb/ follows a module
|
||||
that possibly shared the user's old password - if this old password is
|
||||
not correct the user will be prompted for the correct one. The
|
||||
argument <tt/use_authtok/ is used to <em/force/ this module to set the
|
||||
new password to the one provided by the previously stacked
|
||||
<tt/password/ module (this is used in an example of the stacking of
|
||||
the <em/Cracklib/ module documented above).
|
||||
|
||||
<p>
|
||||
The <tt/not_set_pass/ argument is used to inform the module that it is
|
||||
not to pay attention to/make available the old or new passwords from/to
|
||||
other (stacked) password modules.
|
||||
|
||||
<p>
|
||||
The <tt/debug/ argument makes the password functions of this module
|
||||
<tt/syslog(3)/ more information on its actions. Other arguments may be
|
||||
logged as erroneous to <tt/syslog(3)/.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
An example of the stacking of this module with respect to the
|
||||
pluggable password checking module, <tt/pam_cracklib/, is given in
|
||||
that modules section above.
|
||||
</descrip>
|
||||
|
||||
<sect2>Session component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
No arguments are recognized by this module component. Its action is
|
||||
simply to log the username and the service-type to
|
||||
<tt/syslog(3)/. Messages are logged at the beginning and end of the
|
||||
user's session.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
The use of the session modules is straightforward:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# pwdb - unix like session opening and closing
|
||||
#
|
||||
login session required pam_pwdb.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,117 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_radius.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Cristian Gafton <gafton@redhat.com>
|
||||
-->
|
||||
|
||||
<sect1>The RADIUS session module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_radius/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Cristian Gafton <gafton@redhat.com>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
session
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
This module does not deal with passwords
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
gcc reports 1 warning when compiling <tt>/usr/include/rpc/clnt.h</tt>.
|
||||
Hey, is not my fault !
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
yes; this is a network module (independent of application).
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module is intended to provide the session service for users
|
||||
autheticated with a RADIUS server. At the present stage, the only
|
||||
option supported is the use of the RADIUS server as an accounting
|
||||
server.
|
||||
|
||||
<sect2>Session component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tt/debug/ - verbose logging to <tt/syslog(3)/.
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This module is intended to provide the session service for users
|
||||
autheticated with a RADIUS server. At the present stage, the only
|
||||
option supported is the use of the RADIUS server as an <em/accounting/
|
||||
server.
|
||||
|
||||
<p>
|
||||
(There are few things which needs to be cleared out first in
|
||||
the PAM project until one will be able to use this module and expect
|
||||
it to magically start pppd in response to a RADIUS server command to
|
||||
use PPP for this user, or to initiate a telnet connection to another
|
||||
host, or to hang and call back the user using parameters provided in
|
||||
the RADIUS server response. Most of these things are better suited for
|
||||
the radius login application. I hope to make available Real Soon (tm)
|
||||
patches for the login apps to make it work this way.)
|
||||
|
||||
<p>
|
||||
When opening a session, this module sends an ``Accounting-Start''
|
||||
message to the RADIUS server, which will log/update/whatever a
|
||||
database for this user. On close, an ``Accounting-Stop'' message is
|
||||
sent to the RADIUS server.
|
||||
|
||||
<p>
|
||||
This module has no other prerequisites for making it work. One can
|
||||
install a RADIUS server just for fun and use it as a centralized
|
||||
accounting server and forget about wtmp/last/sac etc. .
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
For the services that need this module (<em/login/ for example) put
|
||||
the following line in <tt>/etc/pam.conf</tt> as the last line for that
|
||||
service (usually after the pam_unix session line):
|
||||
<tscreen>
|
||||
<verb>
|
||||
login session required pam_radius.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
Replace <tt/login/ for each service you are using this module.
|
||||
|
||||
<p>
|
||||
This module make extensive use of the API provided in libpwdb
|
||||
0.54preB or later. By default, it will read the radius server
|
||||
configuration (hostname and secret) from <tt>/etc/raddb/server</tt>.
|
||||
This is a default compiled into libpwdb, and curently there is no way to
|
||||
modify this default without recompiling libpwdb. I am working on
|
||||
extending the radius support from libpwdb to provide a possibility
|
||||
to make this runtime-configurable.
|
||||
|
||||
Also please note that libpwdb will require also the RADIUS
|
||||
dictionary to be present (<tt>/etc/raddb/dictionary</tt>).
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
||||
|
@ -1,157 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_rhosts.sgml,v 1.4 1997/04/05 06:50:42 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The rhosts module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_rhosts_auth/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Al Longyear <longyear@netcom.com>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
Clean.
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
Standard <tt/inet_addr()/, <tt/gethostbyname()/ function calls.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module performs the standard network authentication for services,
|
||||
as used by traditional implementations of <em/rlogin/ and <em/rsh/
|
||||
etc.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/no_hosts_equiv/; <tt/no_rhosts/; <tt/debug/; <tt/no_warn/;
|
||||
<tt/privategroup/; <tt/promiscuous/; <tt/suppress/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
The authentication mechanism of this module is based on the contents
|
||||
of two files; <tt>/etc/hosts.equiv</tt> (or <tt/_PATH_HEQUIV/ in
|
||||
<tt>#include <netdb.h></tt>) and <tt>~/.rhosts</tt>. Firstly,
|
||||
hosts listed in the former file are treated as equivalent to the
|
||||
localhost. Secondly, entries in the user's own copy of the latter file
|
||||
is used to map "<tt/remote-host remote-user/" pairs to that user's
|
||||
account on the current host. Access is granted to the user if their
|
||||
host is present in <tt>/etc/hosts.equiv</tt> and their remote account
|
||||
is identical to their local one, or if their remote account has an
|
||||
entry in their personal configuration file.
|
||||
|
||||
<p>
|
||||
Some restrictions are applied to the attributes of the user's personal
|
||||
configuration file: it must be a regular file (as defined by
|
||||
<tt/S_ISREG(x)/ of POSIX.1); it must be owned by the <em/superuser/ or
|
||||
the user; it must not be writable by any user besides its owner.
|
||||
|
||||
<p>
|
||||
The module authenticates a remote user (internally specified by the
|
||||
item <tt/PAM_RUSER/) connecting from the remote host (internally
|
||||
specified by the item <tt/PAM_RHOST/). Accordingly, for applications
|
||||
to be compatible this authentication module they must set these items
|
||||
prior to calling <tt/pam_authenticate()/. The module is not capable
|
||||
of independently probing the network connection for such information.
|
||||
|
||||
<p>
|
||||
In the case of <tt/root/-access, the <tt>/etc/host.equiv</tt> file is
|
||||
<em/ignored/. Instead, the superuser must have a correctly configured
|
||||
personal configuration file.
|
||||
|
||||
<p>
|
||||
The behavior of the module is modified by flags:
|
||||
<itemize>
|
||||
<item>
|
||||
<tt/debug/ -
|
||||
log more information to <tt/syslog(3)/. (XXX - actually, this module
|
||||
does not do any logging currently, please volunteer to fix this!)
|
||||
|
||||
<item>
|
||||
<tt/no_warn/ -
|
||||
do not give verbal warnings to the user about failures etc. (XXX -
|
||||
this module currently does not issue any warnings, please volunteer to
|
||||
fix this!)
|
||||
|
||||
<item>
|
||||
<tt/no_hosts_equiv/ -
|
||||
ignore the contents of the <tt>/etc/hosts.equiv</tt> file.
|
||||
|
||||
<item>
|
||||
<tt/no_rhosts/ -
|
||||
ignore the contents of all user's personal configuration file
|
||||
<tt>~/.rhosts</tt>.
|
||||
|
||||
<item>
|
||||
<tt/privategroup/ -
|
||||
normally, the <tt>~/.rhosts</tt> file must not be writable by anyone
|
||||
other than its owner. This option overlooks group write access in the
|
||||
case that the group owner of this file has the same name as the
|
||||
user being authenticated. To lessen the security problems associated
|
||||
with this option, the module also checks that the user is the only
|
||||
member of their private group.
|
||||
|
||||
<item>
|
||||
<tt/promiscuous/ -
|
||||
A host entry of `+' will lead to all hosts being granted
|
||||
access. Without this option, '+' entries will be ignored. Note, that
|
||||
the <tt/debug/ option will syslog a warning in this latter case.
|
||||
|
||||
<item>
|
||||
<tt/suppress/ -
|
||||
This will prevent the module from <tt/syslog(3)/ing a warning message
|
||||
when this authentication fails. This option is mostly for keeping
|
||||
logs free of meaningless errors, in particular when the module is used
|
||||
with the <tt/sufficient/ control flag.
|
||||
|
||||
</itemize>
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
To allow users to login from trusted remote machines, you should try
|
||||
adding the following line to your <tt>/etc/pam.conf</tt> file
|
||||
<em/before/ the line that would otherwise prompt the user for a
|
||||
password:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# No passwords required for users from hosts listed above.
|
||||
#
|
||||
login auth sufficient pam_rhosts_auth.so no_rhosts
|
||||
</verb>
|
||||
</tscreen>
|
||||
Note, in this example, the system administrator has turned off all
|
||||
<em/personal/ <em/rhosts/ configuration files. Also note, that this module
|
||||
can be used to <em/only/ allow remote login from hosts specified in
|
||||
the <tt>/etc/host.equiv</tt> file, by replacing <tt/sufficient/ in the
|
||||
above example with <tt/required/.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,85 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_rootok.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>The root access module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
pam_rootok
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
<bf>Linux-PAM</bf> maintainer
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
Clean.
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module is for use in situations where the superuser wishes
|
||||
to gain access to a service without having to enter a password.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This module authenticates the user if their <tt/uid/ is <tt/0/.
|
||||
Applications that are created <em/setuid/-root generally retain the
|
||||
<tt/uid/ of the user but run with the authority of an enhanced
|
||||
<em/effective-/<tt/uid/. It is the real <tt/uid/ that is checked.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
In the case of the <tt/su/ application the historical usage is to
|
||||
permit the superuser to adopt the identity of a lesser user without
|
||||
the use of a password. To obtain this behavior under <tt/Linux-PAM/
|
||||
the following pair of lines are needed for the corresponding entry in
|
||||
the configuration file:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# su authentication. Root is granted access by default.
|
||||
#
|
||||
su auth sufficient pam_rootok.so
|
||||
su auth required pam_unix_auth.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
<p>
|
||||
Note. For programs that are run by the superuser (or started when the
|
||||
system boots) this module should not be used to authenticate users.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,72 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_securetty.sgml,v 1.1 1996/11/30 20:59:32 morgan Exp $
|
||||
|
||||
This file was written by Michael K. Johnson <johnsonm@redhat.com>
|
||||
-->
|
||||
|
||||
<sect1>The securetty module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_securetty/
|
||||
|
||||
<tag><bf>Author[s]:</bf></tag>
|
||||
Elliot Lee <sopwith@cuc.edu>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Red Hat Software:<newline>
|
||||
<em/currently/ Michael K. Johnson <johnsonm@redhat.com><newline>
|
||||
(if unavailable, contact Elliot Lee <sopwith@cuc.edu>).
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
<tt>/etc/securetty</tt> file
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
Requires the application to fill in the <tt>PAM_TTY</tt> item
|
||||
correctly in order to act meaningfully.
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
Provides standard Unix securetty checking.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
Provides standard Unix securetty checking, which causes authentication
|
||||
for root to fail unless <tt>PAM_TTY</tt> is set to a string listed in
|
||||
the <tt>/etc/securetty</tt> file. For all other users, it succeeds.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
For canonical usage, should be listed as a <tt>required</tt>
|
||||
authentication method before any <tt>sufficient</tt> authentication
|
||||
methods.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,166 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_time.sgml,v 1.2 1997/02/15 18:25:44 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>Time control
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_time/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <tt><morgan@parc.power.net></tt>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
account
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
Requires a configuration file <tt>/etc/security/time.conf</tt>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
Through the <tt/PAM_TTY/ item only
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
Running a well regulated system occasionally involves restricting
|
||||
access to certain services in a selective manner. This module offers
|
||||
some time control for access to services offered by a system. Its
|
||||
actions are determined with a configuration file. This module can be
|
||||
configured to deny access to (individual) users based on their name,
|
||||
the time of day, the day of week, the service they are applying for
|
||||
and their terminal from which they are making their request.
|
||||
|
||||
<sect2>Account component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This module bases its actions on the rules listed in its configuration
|
||||
file: <tt>/etc/security/pam.conf</tt>. Each rule has the following
|
||||
form,
|
||||
<tscreen>
|
||||
<em/services/<tt/;/<em/ttys/<tt/;/<em/users/<tt/;/<em/times/
|
||||
</tscreen>
|
||||
In words, each rule occupies a line, terminated with a newline or the
|
||||
beginning of a comment; a `<tt/#/'. It contains four fields separated
|
||||
with semicolons, `<tt/;/'. The fields are as follows:
|
||||
|
||||
<p>
|
||||
<itemize>
|
||||
<item><em/services/ -
|
||||
a logic list of service names that are affected by this rule.
|
||||
|
||||
<item><em/ttys/ -
|
||||
a logic list of terminal names indicating those terminals covered by
|
||||
the rule.
|
||||
|
||||
<item><em/user/ -
|
||||
a logic list of usernames to which this rule applies
|
||||
|
||||
<p>
|
||||
By a logic list we mean a sequence of tokens (associated with the
|
||||
appropriate <tt/PAM_/ item), containing no more than one wildcard
|
||||
character; `<tt/*/', and optionally prefixed with a negation operator;
|
||||
`<tt/!/'. Such a sequence is concatenated with one of two logical
|
||||
operators: <tt/&/ (logical AND) and <tt/|/ (logical OR). Two
|
||||
examples are: <tt>!morgan&!root</tt>, indicating that this rule
|
||||
does not apply to the user <tt>morgan</tt> nor to <tt>root</tt>; and
|
||||
<tt>tty*&!ttyp*</tt>, which indicates that the rule applies only
|
||||
to console terminals but not pseudoterminals.
|
||||
|
||||
<item><em/times/ - a logic list of times at which this rule
|
||||
applies. The format of each element is a day/time-range. The days are
|
||||
specified by a sequence of two character entries. For example,
|
||||
<tt/MoTuSa/, indicates Monday Tuesday and Saturday. Note that
|
||||
repeated days are <em/unset/; <tt/MoTuMo/ indicates Tuesday, and
|
||||
<tt/MoWk/ means all weekdays bar Monday. The two character
|
||||
combinations accepted are,
|
||||
<tscreen>
|
||||
<verb>
|
||||
Mo Tu We Th Fr Sa Su Wk Wd Al
|
||||
</verb>
|
||||
</tscreen>
|
||||
The last two of these being <em/weekend/ days and <em/all 7 days/ of
|
||||
the week respectively.
|
||||
|
||||
<p>
|
||||
The time range part is a pair of 24-hour times, <em/HHMM/, separated
|
||||
by a hyphen -- indicating the start and finish time for the rule. If
|
||||
the finsish time is smaller than the start time, it is assumed to
|
||||
apply on the following day. For an example, <tt/Mo1800-0300/ indicates
|
||||
that the permitted times are Monday night from 6pm to 3am the
|
||||
following morning.
|
||||
|
||||
</itemize>
|
||||
|
||||
<p>
|
||||
Note, that the given time restriction is only applied when the first
|
||||
three fields are satisfied by a user's application for service.
|
||||
|
||||
<p>
|
||||
For convenience and readability a rule can be extended beyond a single
|
||||
line with a `<tt>\</tt><em/newline/'.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
The use of this module is initiated with an entry in the
|
||||
<bf/Linux-PAM/ configuration file of the following type:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# apply pam_time accounting to login requests
|
||||
#
|
||||
login account required pam_time.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
where, here we are applying the module to the <em/login/ application.
|
||||
|
||||
<p>
|
||||
Some examples of rules that can be placed in the
|
||||
<tt>/etc/security/time.conf</tt> configuration file are the following:
|
||||
<descrip>
|
||||
|
||||
<tag><tt>login ; tty* & ; !ttyp* ; !root ; !Al0000-2400</tt></tag>
|
||||
all users except for <tt/root/ are denied access to console-login at
|
||||
all times.
|
||||
|
||||
<tag><tt>games ; * ; !waster ; Wd0000-2400 | Wk1800-0800</tt></tag>
|
||||
games (configured to use Linux-PAM) are only to be accessed out of
|
||||
working hours. This rule does not apply to the user <tt/waster/.
|
||||
|
||||
</descrip>
|
||||
|
||||
<p>
|
||||
Note, currently there is no daemon enforcing the end of a session.
|
||||
This needs to be remedied.
|
||||
|
||||
<p>
|
||||
Poorly formatted rules are logged as errors using <tt/syslog(3)/.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,67 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_warn.sgml,v 1.1 1996/11/30 20:59:32 morgan Exp $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
-->
|
||||
|
||||
<sect1>Warning logger module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_warn/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Andrew G. Morgan <morgan@parc.power.net>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication; password
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
logs information about the remote user and host (if pam-items are known)
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
This module is principally for logging information about a
|
||||
proposed authentication or application to update a password.
|
||||
|
||||
<sect2>Authentication+Password component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
Log the service, terminal, user, remote user and remote host to
|
||||
<tt/syslog(3)/. The items are not probed for, but instead obtained
|
||||
from the standard pam-items.
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
an example is provided in the configuration file section <ref
|
||||
id="configuration" name="above">.
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,124 +0,0 @@
|
||||
<!--
|
||||
$Id: pam_wheel.sgml,v 1.3 1997/02/15 18:25:44 morgan Exp morgan $
|
||||
|
||||
This file was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
from notes provided by Cristian Gafton.
|
||||
-->
|
||||
|
||||
<sect1>The wheel module
|
||||
|
||||
<sect2>Synopsis
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Module Name:</bf></tag>
|
||||
<tt/pam_wheel/
|
||||
|
||||
<tag><bf>Author:</bf></tag>
|
||||
Cristian Gafton <gafton@redhat.com>
|
||||
|
||||
<tag><bf>Maintainer:</bf></tag>
|
||||
Author.
|
||||
|
||||
<tag><bf>Management groups provided:</bf></tag>
|
||||
authentication
|
||||
|
||||
<tag><bf>Cryptographically sensitive:</bf></tag>
|
||||
|
||||
<tag><bf>Security rating:</bf></tag>
|
||||
|
||||
<tag><bf>Clean code base:</bf></tag>
|
||||
|
||||
<tag><bf>System dependencies:</bf></tag>
|
||||
Requires libpwdb.
|
||||
|
||||
<tag><bf>Network aware:</bf></tag>
|
||||
|
||||
</descrip>
|
||||
|
||||
<sect2>Overview of module
|
||||
|
||||
<p>
|
||||
Only permit root access to members of the wheel (<tt/gid=0/) group.
|
||||
|
||||
<sect2>Authentication component
|
||||
|
||||
<p>
|
||||
<descrip>
|
||||
|
||||
<tag><bf>Recognized arguments:</bf></tag>
|
||||
<tt/debug/;
|
||||
<tt/use_uid/;
|
||||
<tt/trust/;
|
||||
<tt/deny/;
|
||||
<tt/group=XXXX/
|
||||
|
||||
<tag><bf>Description:</bf></tag>
|
||||
|
||||
This module is used to enforce the so-called wheel group. By default,
|
||||
it permits root access to the system if the applicant user is a member
|
||||
of the <tt/wheel/ group (better described as the group with group-id
|
||||
<tt/0/).
|
||||
|
||||
<p>
|
||||
The action of the module may be modified from this default by one or
|
||||
more of the following flags in the <tt>/etc/pam.conf</tt> file.
|
||||
<itemize>
|
||||
<item>
|
||||
<tt/debug/ -
|
||||
Supply more debugging information to <tt/syslog(3)/.
|
||||
|
||||
<item>
|
||||
<tt/use_id/ -
|
||||
This option modifies the behavior of the module by using the current
|
||||
<tt/uid/ of the process and not the <tt/getlogin(3)/ name of the user.
|
||||
This option is useful for being able to jump from one account to
|
||||
another, for example with 'su'.
|
||||
|
||||
<item>
|
||||
<tt/trust/ -
|
||||
This option instructs the module to return <tt/PAM_SUCCESS/ should it
|
||||
find the user applying for root privilege is a member of the wheel
|
||||
group. The default action is to return <tt/PAM_IGNORE/ in this
|
||||
situation. By using the <tt/trust/ option it is possible to arrange
|
||||
for <tt/wheel/-group members to become root without typing a
|
||||
password. <bf/USE WITH CARE/.
|
||||
|
||||
<item>
|
||||
<tt/deny/ -
|
||||
This is used to reverse the logic of the module's behavior.
|
||||
If the user is trying to get <tt/uid=0/ access and is a member of the wheel
|
||||
group, deny access (for the wheel group, this is perhaps nonsense!):
|
||||
it is intended for use in conjunction with the <tt/group=/ argument...
|
||||
|
||||
<item>
|
||||
<tt/group=XXXX/ -
|
||||
Instead of checking the <tt/gid=0/ group, use the user's <tt/XXXX/
|
||||
group membership for the authentication. Here, <tt/XXXX/ is the name
|
||||
of the group and <bf/not/ its numeric identifier.
|
||||
|
||||
</itemize>
|
||||
|
||||
<tag><bf>Examples/suggested usage:</bf></tag>
|
||||
|
||||
To restrict access to superuser status to the members of the
|
||||
<tt/wheel/ group, use the following entries in your configuration
|
||||
file:
|
||||
<tscreen>
|
||||
<verb>
|
||||
#
|
||||
# root gains access by default (rootok), only wheel members can
|
||||
# become root (wheel) but Unix authenticate non-root applicants.
|
||||
#
|
||||
su auth sufficient pam_rootok.so
|
||||
su auth required pam_wheel.so
|
||||
su auth required pam_unix_auth.so
|
||||
</verb>
|
||||
</tscreen>
|
||||
|
||||
</descrip>
|
||||
|
||||
<!--
|
||||
End of sgml insert for this module.
|
||||
-->
|
@ -1,3 +0,0 @@
|
||||
$Id: README,v 1.1 1996/11/10 19:28:16 morgan Exp $
|
||||
|
||||
this is the directory for the postscipt documentation
|
@ -1,270 +0,0 @@
|
||||
PAM working group ## A.G. Morgan
|
||||
Internet Draft: ## March 24, 1998
|
||||
Document: draft-morgan-pam-00.txt ##
|
||||
Expires: September 24, 1998 ##
|
||||
Obsoletes: ##
|
||||
|
||||
## Pluggable Authentication Modules ##
|
||||
|
||||
#$ Status of this memo
|
||||
|
||||
This document is an Internet-Draft. Internet-Drafts are working
|
||||
documents of the Internet Engineering Task Force (IETF), its areas,
|
||||
and its working groups. Note that other groups may also distribute
|
||||
working documents as Internet-Drafts.
|
||||
|
||||
Internet-Drafts are draft documents valid for a maximum of six months
|
||||
and may be updated, replaced, or obsoleted by other documents at any
|
||||
time. It is inappropriate to use Internet- Drafts as reference
|
||||
material or to cite them other than as "work in progress."
|
||||
|
||||
To view the entire list of current Internet-Drafts, please check the
|
||||
"1id-abstracts.txt" listing contained in the Internet-Drafts Shadow
|
||||
Directories on ftp.is.co.za (Africa), ftp.nordu.net (Northern Europe),
|
||||
ftp.nis.garr.it (Southern Europe), munnari.oz.au (Pacific Rim),
|
||||
ftp.ietf.org (US East Coast), or ftp.isi.edu (US West Coast).
|
||||
|
||||
#$ Abstract
|
||||
|
||||
This document is concerned with the definition of a general
|
||||
infrastructure for module based authentication. The infrastructure is
|
||||
named Pluggable Authentication Modules (PAM for short).
|
||||
|
||||
#$ Introduction
|
||||
|
||||
Computers are tools. They provide services to people and other
|
||||
computers (collectively we shall call these "users" entities). In
|
||||
order to provide convenient, reliable and individual service to
|
||||
different entities, it is common for entities to be labelled. Having
|
||||
defined a label as refering to a some specific entity, the label is
|
||||
used for the purpose of protecting and allocating data resources.
|
||||
|
||||
All modern operating systems have a notion of labelled entities and
|
||||
all modern operating systems face a common problem: how to
|
||||
authenticate the association of a predefined label with applicant
|
||||
entities.
|
||||
|
||||
There are as many authentication methods as one might care to count.
|
||||
None of them are perfect and none of them are invulnerable. In
|
||||
general, any given authentication method becomes weaker over time. It
|
||||
is common then for new authentication methods to be developed in
|
||||
response to newly discovered weaknesses in the old authentication
|
||||
methods.
|
||||
|
||||
The problem with reinventing authentication methods is the fact that
|
||||
old applications do not support them. This contributes to an inertia
|
||||
that discourages the overhaul of weakly protected systems. Another
|
||||
problem is that individuals (people) are frequently powerless to layer
|
||||
the protective authentication around their systems. They are forced
|
||||
to rely on single (lowest common denominator) authentication schemes
|
||||
even in situations where this is far from appropriate.
|
||||
|
||||
PAM, as discussed in this document, is a generalization of the
|
||||
approach first introduced in [#$R#{OSF_RFC_PAM}]. In short, it is a
|
||||
general framework of interfaces that abstract the process of
|
||||
authentication. With PAM, a service provider can custom protect
|
||||
individual services to the level that they deam is appropriate.
|
||||
|
||||
PAM has nothing explicit to say about transport layer encryption.
|
||||
Within the context of this document encryption and/or compression of
|
||||
data exchanges are application specific (strictly between client and
|
||||
server).
|
||||
|
||||
#$ Definitions
|
||||
|
||||
Here we pose the authentication problem as one of configuring defined
|
||||
interfaces between two entities.
|
||||
|
||||
#$$#{players} Players in the authentication process
|
||||
|
||||
PAM reserves the following words to specify unique entities in the
|
||||
authentication process:
|
||||
|
||||
applicant
|
||||
the entity (user) initiating an application for service
|
||||
[PAM associates PAM_RUSER with this requesting user].
|
||||
|
||||
arbitrator
|
||||
the entity (user) under who's identity the service application
|
||||
is negotiated and with who's authority service is granted.
|
||||
|
||||
user
|
||||
the entity (user) who's identity is being authenticated
|
||||
[PAM associates PAM_USER with this identity].
|
||||
|
||||
server
|
||||
the application that provides service, or acts as an
|
||||
authenticated gateway to the requested service. This
|
||||
application is completely responsible for the transport
|
||||
layer. PAM makes no assumptions about how data is
|
||||
exchanged between the server and the client.
|
||||
|
||||
client
|
||||
application providing the direct/primary interface to
|
||||
applicant. This application is completely responsible
|
||||
for transporting client-side data to the server.
|
||||
PAM makes no assumptions about how data is exchanged between
|
||||
the client and the server.
|
||||
|
||||
module
|
||||
authentication binary that provides server-side support for
|
||||
some authentication method.
|
||||
|
||||
agent
|
||||
authentication binary that provides client-side support for
|
||||
some authentication method.
|
||||
|
||||
#$$ Special cases
|
||||
|
||||
In the previous section (#{players}) we identified the most general
|
||||
selection of authentication participants. In the case of network
|
||||
authentication, it is easy to ascribe identities to the defined
|
||||
players. However, there are special (less general) cases and we
|
||||
recognize them here.
|
||||
|
||||
The primary authentication step, when a user is directly introduced
|
||||
into a computer system (log's on to a workstation) is a special case.
|
||||
In this situation, the "client" and the "server" are generally one
|
||||
application. Before authenticating such a user, the "applicant" is
|
||||
formally unknown.
|
||||
|
||||
#$ Defined interfaces
|
||||
|
||||
Here, we discuss the formal interfaces between the players in the
|
||||
authentication process.
|
||||
|
||||
#$$#{applicant_client} Applicant <-> client
|
||||
|
||||
Once the client is invoked, requests to the applicant entity are
|
||||
initiated by the client application. General clients are able to make
|
||||
the following requests to an applicant:
|
||||
|
||||
echo text
|
||||
echo error
|
||||
prompt for echo'd text input
|
||||
prompt for concealed text input
|
||||
|
||||
the nature of the interface provided by the client for the benefit of
|
||||
the applicant entity is client specific and not defined by PAM.
|
||||
|
||||
#$$ Client <-> agent
|
||||
|
||||
In general, authentication schemes require more modes of exchange than
|
||||
the four defined in the previous section (#{applicant_client}). This
|
||||
provides a role for client-loadable agents. The client and agent
|
||||
exchange binary-messages that can have one of the following forms:
|
||||
|
||||
client -> agent
|
||||
prompt for binary data packet using a binary packet
|
||||
|
||||
agent -> client
|
||||
set environment variable
|
||||
get environment variable
|
||||
echo text
|
||||
echo error
|
||||
prompt for echo'd text input
|
||||
prompt for concealed text input
|
||||
|
||||
The single defined procedure for exchange is that the client first
|
||||
prompts the agent with a binary packet and expects to receive a binary
|
||||
(response) packet in return. Before returning the binary response,
|
||||
the agent may request an arbitrary number of exchanges with the client.
|
||||
|
||||
#$$ Client <-> server
|
||||
|
||||
Once the client has established a connection with the server (the
|
||||
nature of the transport protocol is not specified by PAM), the server
|
||||
is reponsible for driving the authentication process.
|
||||
|
||||
General servers can request the following from the client:
|
||||
|
||||
(directed to the applicant)
|
||||
echo text
|
||||
echo error
|
||||
prompt for echo'd text response
|
||||
prompt for concealed text response
|
||||
|
||||
(directed to the appropriate agent)
|
||||
binary prompt for a binary response
|
||||
|
||||
Client side agents are required to process binary prompts. Their
|
||||
binary responses are passed directly back to the server.
|
||||
|
||||
#$$ Server <-> module
|
||||
|
||||
Modules drive the authentication process. The server provides a
|
||||
conversation function with which it encapsulates module-generated
|
||||
requests and exchanges them with the client.
|
||||
|
||||
General conversation functions can support the following five
|
||||
"conversation" requests:
|
||||
|
||||
echo text
|
||||
echo error
|
||||
prompt for echo'd text response
|
||||
prompt for concealed text response
|
||||
prompt for binary packet with binary packet
|
||||
|
||||
The server is responsible for redirecting these requests to the
|
||||
client.
|
||||
|
||||
#$ C API for defined interfaces
|
||||
|
||||
#$$ Applicant <-> client
|
||||
|
||||
No API is defined for this interface. The interface is considered to
|
||||
be specific to the client application. Example applications include
|
||||
terminal login, (X)windows login, machine file transfer applications.
|
||||
|
||||
#$$ Client <-> agent
|
||||
|
||||
This interface is concerned with the exchange of "binary prompts". A
|
||||
binary prompt has the following form: { 4 8-bit bytes in network order
|
||||
encoding an unsigened 32 bit integer (length), 4 8-bit bytes in
|
||||
network order encoding an unsigened 32 bit integer (control),
|
||||
"length-4" 8-bit bytes bytes comprising upto 2^32-4 bytes of binary
|
||||
data }.
|
||||
|
||||
## [ u32 | u32 | (length-4 bytes) ] ##
|
||||
## length control data ##
|
||||
|
||||
The composition of the "data" is not specified. Valid control values
|
||||
are:
|
||||
|
||||
##control value | used by | description ##
|
||||
##------------------------------------------------------------------##
|
||||
## | | ##
|
||||
##PAMC_CONTROL_OK | agent | agent is happy ##
|
||||
##PAMC_CONTROL_FAIL | agent | agent failed ##
|
||||
##PAMC_CONTROL_BUSY | agent | agent is busy ##
|
||||
##PAMC_CONTROL_PUTENV | agent | set envvar of client ##
|
||||
##PAMC_CONTROL_GETENV | agent | want envvar of client ##
|
||||
##PAMC_CONTROL_GETECHO | agent | echo'd prompt to applicant##
|
||||
##PAMC_CONTROL_GETNOECHO | agent | secret prompt to applicant##
|
||||
##PAMC_CONTROL_PUTTEXT | agent | echo text to applicant ##
|
||||
##PAMC_CONTROL_SELECT | client | client selects named agent##
|
||||
##PAMC_CONTROL_EXCHANGE | client+agent | data exchange packet ##
|
||||
##PAMC_CONTROL_DONE | agent | agent has completed ##
|
||||
##PAMC_CONTROL_EMPTY | agent | agent has no reply ##
|
||||
|
||||
#$ Security considerations
|
||||
|
||||
This document is devoted to standardizing authentication
|
||||
infrastructure: everything in this document has implications for
|
||||
security.
|
||||
|
||||
#$ Contact
|
||||
|
||||
The email list for discussing issues related to this document is
|
||||
<pam-list@redhat.com>.
|
||||
|
||||
#$ References
|
||||
|
||||
[#{OSF_RFC_PAM}] OSF RFC 86.0, "Unified Login with Pluggable Authentication
|
||||
Modules (PAM)", October 1995
|
||||
|
||||
#$ Author's Address
|
||||
|
||||
Andrew Morgan
|
||||
Email: morgan@ftp.kernel.org
|
||||
|
@ -1,16 +0,0 @@
|
||||
LIBS=-lfl
|
||||
|
||||
padout: parse.tab.o
|
||||
$(CC) -o padout parse.tab.o $(LIBS)
|
||||
|
||||
parse.tab.o: parse.tab.c lex.yy.c
|
||||
$(CC) -c parse.tab.c
|
||||
|
||||
parse.tab.c: parse.y
|
||||
bison parse.y
|
||||
|
||||
lex.yy.c: parse.lex
|
||||
flex parse.lex
|
||||
|
||||
clean:
|
||||
rm -f parse.tab.o parse.tab.c lex.yy.c padout *~ core
|
@ -1,11 +0,0 @@
|
||||
%%
|
||||
|
||||
\#[\$]+[a-zA-Z]*(\=[0-9]+)? return NEW_COUNTER;
|
||||
\#\{[a-zA-Z][a-zA-Z0-9\_]*\} return LABEL;
|
||||
\# return NO_INDENT;
|
||||
\#\# return RIGHT;
|
||||
\\\# return HASH;
|
||||
[^\n] return CHAR;
|
||||
[\n] return NEWLINE;
|
||||
|
||||
%%
|
@ -1,293 +0,0 @@
|
||||
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAXLINE 1000
|
||||
#define INDENT_STRING " "
|
||||
#define PAPER_WIDTH 74
|
||||
|
||||
int indent=0;
|
||||
int line=1;
|
||||
char *last_label=NULL;
|
||||
|
||||
extern void yyerror(const char *x);
|
||||
extern char *get_label(const char *label);
|
||||
extern void set_label(const char *label, const char *target);
|
||||
char *new_counter(const char *key);
|
||||
|
||||
#include "lex.yy.c"
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
int def;
|
||||
char *string;
|
||||
}
|
||||
|
||||
%token NEW_COUNTER LABEL HASH CHAR NEWLINE NO_INDENT RIGHT
|
||||
%type <string> stuff text
|
||||
|
||||
%start doc
|
||||
|
||||
%%
|
||||
|
||||
doc:
|
||||
| doc NEWLINE {
|
||||
printf("\n");
|
||||
++line;
|
||||
}
|
||||
| doc stuff NEWLINE {
|
||||
if (strlen($2) > (PAPER_WIDTH-(indent ? strlen(INDENT_STRING):0))) {
|
||||
yyerror("line too long");
|
||||
}
|
||||
printf("%s%s\n", indent ? INDENT_STRING:"", $2);
|
||||
free($2);
|
||||
indent = 1;
|
||||
++line;
|
||||
}
|
||||
| doc stuff RIGHT stuff NEWLINE {
|
||||
char fixed[PAPER_WIDTH+1];
|
||||
int len;
|
||||
|
||||
len = PAPER_WIDTH-(strlen($2)+strlen($4));
|
||||
|
||||
if (len >= 0) {
|
||||
memset(fixed, ' ', len);
|
||||
fixed[len] = '\0';
|
||||
} else {
|
||||
yyerror("line too wide");
|
||||
fixed[0] = '\0';
|
||||
}
|
||||
printf("%s%s%s\n", $2, fixed, $4);
|
||||
free($2);
|
||||
free($4);
|
||||
indent = 1;
|
||||
++line;
|
||||
}
|
||||
| doc stuff RIGHT stuff RIGHT stuff NEWLINE {
|
||||
char fixed[PAPER_WIDTH+1];
|
||||
int len, l;
|
||||
|
||||
len = PAPER_WIDTH-(strlen($2)+strlen($4));
|
||||
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
yyerror("line too wide");
|
||||
}
|
||||
|
||||
l = len/2;
|
||||
memset(fixed, ' ', l);
|
||||
fixed[l] = '\0';
|
||||
printf("%s%s%s", $2, fixed, $4);
|
||||
free($2);
|
||||
free($4);
|
||||
|
||||
l = (len+1)/2;
|
||||
memset(fixed, ' ', l);
|
||||
fixed[l] = '\0';
|
||||
printf("%s%s\n", fixed, $6);
|
||||
free($6);
|
||||
|
||||
indent = 1;
|
||||
++line;
|
||||
}
|
||||
| doc stuff RIGHT stuff RIGHT stuff NEWLINE {
|
||||
char fixed[PAPER_WIDTH+1];
|
||||
int len, l;
|
||||
|
||||
len = PAPER_WIDTH-(strlen($2)+strlen($4));
|
||||
|
||||
if (len < 0) {
|
||||
len = 0;
|
||||
yyerror("line too wide");
|
||||
}
|
||||
|
||||
l = len/2;
|
||||
memset(fixed, ' ', l);
|
||||
fixed[l] = '\0';
|
||||
printf("%s%s%s", $2, fixed, $4);
|
||||
free($2);
|
||||
free($4);
|
||||
|
||||
l = (len+1)/2;
|
||||
memset(fixed, ' ', l);
|
||||
fixed[l] = '\0';
|
||||
printf("%s%s\n", fixed, $6);
|
||||
free($6);
|
||||
|
||||
indent = 1;
|
||||
++line;
|
||||
}
|
||||
;
|
||||
|
||||
stuff: {
|
||||
$$ = strdup("");
|
||||
}
|
||||
| stuff text {
|
||||
$$ = malloc(strlen($1)+strlen($2)+1);
|
||||
sprintf($$,"%s%s", $1, $2);
|
||||
free($1);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
text: CHAR {
|
||||
$$ = strdup(yytext);
|
||||
}
|
||||
| text CHAR {
|
||||
$$ = malloc(strlen($1)+2);
|
||||
sprintf($$,"%s%s", $1, yytext);
|
||||
free($1);
|
||||
}
|
||||
| NO_INDENT {
|
||||
$$ = strdup("");
|
||||
indent = 0;
|
||||
}
|
||||
| HASH {
|
||||
$$ = strdup("#");
|
||||
}
|
||||
| LABEL {
|
||||
if (($$ = get_label(yytext)) == NULL) {
|
||||
set_label(yytext, last_label);
|
||||
$$ = strdup("");
|
||||
}
|
||||
}
|
||||
| NEW_COUNTER {
|
||||
$$ = new_counter(yytext);
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
typedef struct node_s {
|
||||
struct node_s *left, *right;
|
||||
const char *key;
|
||||
char *value;
|
||||
} *node_t;
|
||||
|
||||
node_t label_root = NULL;
|
||||
node_t counter_root = NULL;
|
||||
|
||||
const char *find_key(node_t root, const char *key)
|
||||
{
|
||||
while (root) {
|
||||
int cmp = strcmp(key, root->key);
|
||||
|
||||
if (cmp > 0) {
|
||||
root = root->right;
|
||||
} else if (cmp) {
|
||||
root = root->left;
|
||||
} else {
|
||||
return root->value;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
node_t set_key(node_t root, const char *key, const char *value)
|
||||
{
|
||||
if (root) {
|
||||
int cmp = strcmp(key, root->key);
|
||||
if (cmp > 0) {
|
||||
root->right = set_key(root->right, key, value);
|
||||
} else if (cmp) {
|
||||
root->left = set_key(root->left, key, value);
|
||||
} else {
|
||||
free(root->value);
|
||||
root->value = strdup(value);
|
||||
}
|
||||
} else {
|
||||
root = malloc(sizeof(struct node_s));
|
||||
root->right = root->left = NULL;
|
||||
root->key = strdup(key);
|
||||
root->value = strdup(value);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
void yyerror(const char *x)
|
||||
{
|
||||
fprintf(stderr, "line %d: %s\n", line, x);
|
||||
}
|
||||
|
||||
char *get_label(const char *label)
|
||||
{
|
||||
const char *found = find_key(label_root, label);
|
||||
|
||||
if (found) {
|
||||
return strdup(found);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void set_label(const char *label, const char *target)
|
||||
{
|
||||
if (target == NULL) {
|
||||
yyerror("no hanging value for label");
|
||||
target = "<??>";
|
||||
}
|
||||
label_root = set_key(label_root, label, target);
|
||||
}
|
||||
|
||||
char *new_counter(const char *key)
|
||||
{
|
||||
int i=0, j, ndollars = 0;
|
||||
const char *old;
|
||||
char *new;
|
||||
|
||||
if (key[i++] != '#') {
|
||||
yyerror("bad index");
|
||||
return strdup("<???>");
|
||||
}
|
||||
|
||||
while (key[i] == '$') {
|
||||
++ndollars;
|
||||
++i;
|
||||
}
|
||||
|
||||
key += i;
|
||||
old = find_key(counter_root, key);
|
||||
new = malloc(20*ndollars);
|
||||
|
||||
if (old) {
|
||||
for (j=0; ndollars > 1 && old[j]; ) {
|
||||
if (old[j++] == '.' && --ndollars <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j) {
|
||||
strncpy(new, old, j);
|
||||
}
|
||||
if (old[j]) {
|
||||
i = atoi(old+j);
|
||||
} else {
|
||||
new[j++] = '.';
|
||||
i = 0;
|
||||
}
|
||||
} else {
|
||||
j=0;
|
||||
while (--ndollars > 0) {
|
||||
new[j++] = '0';
|
||||
new[j++] = '.';
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
new[j] = '\0';
|
||||
sprintf(new+j, "%d", ++i);
|
||||
|
||||
counter_root = set_key(counter_root, key, new);
|
||||
|
||||
if (last_label) {
|
||||
free(last_label);
|
||||
}
|
||||
last_label = strdup(new);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
yyparse();
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
$Id: README,v 1.1 1996/11/10 19:18:06 morgan Exp $
|
||||
|
||||
This is a directory for text versions of the pam documentation
|
@ -1,42 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.10 1996/11/10 19:50:59 morgan Exp $
|
||||
#
|
||||
|
||||
dummy:
|
||||
|
||||
@echo "*** This is not a top level Makefile!"
|
||||
|
||||
PROGS = blank xsh check_user
|
||||
SRCS = blank.c xsh.c check_user.c
|
||||
|
||||
# have removed the following pair since they no longer conform to
|
||||
# any recognized conventions: vpass test
|
||||
# ditto: vpass.c test.c
|
||||
|
||||
PROGSUID =
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
check_user: check_user.o
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LOADLIBES)
|
||||
|
||||
blank: blank.o
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LOADLIBES)
|
||||
|
||||
xsh: xsh.o
|
||||
$(CC) $(CFLAGS) -o $@ $< $(LOADLIBES)
|
||||
|
||||
install: all
|
||||
if [ -n "$(PROGS)" ]; then cp $(PROGS) ../bin ; fi
|
||||
if [ -n "$(PROGSUID)" ]; then \
|
||||
$(INSTALL) -m 4555 -o root -g bin $(PROGSUID) ../bin ; fi
|
||||
|
||||
clean:
|
||||
rm -f *.a *.so *.o *~ $(PROGS) $(PROGSUID)
|
||||
|
||||
remove:
|
||||
cd ../bin ; rm -f $(PROGS) $(PROGSUID)
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.out *.o *.so
|
||||
for x in $(PROGS) $(PROGSUID) ; do rm -f ../bin/$$x ; done
|
@ -1,173 +0,0 @@
|
||||
/*
|
||||
* $Id: blank.c,v 1.7 1996/12/01 03:16:53 morgan Exp morgan $
|
||||
*
|
||||
* $Log: blank.c,v $
|
||||
* Revision 1.7 1996/12/01 03:16:53 morgan
|
||||
* added setcred closing function
|
||||
*
|
||||
* Revision 1.6 1996/11/10 19:51:40 morgan
|
||||
* minor change to avoid gcc warning
|
||||
*
|
||||
* Revision 1.5 1996/07/07 23:53:05 morgan
|
||||
* added optional fail delay (non-standard Linux-PAM)
|
||||
*
|
||||
* Revision 1.4 1996/05/02 04:44:18 morgan
|
||||
* moved conversation to a libmisc library routine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/* Andrew Morgan (morgan@parc.power.net) -- a self contained `blank'
|
||||
* application
|
||||
*
|
||||
* I am not very proud of this code. It makes use of a possibly ill-
|
||||
* defined pamh pointer to call pam_strerror() with. The reason that
|
||||
* I was sloppy with this is historical (pam_strerror, prior to 0.59,
|
||||
* did not require a pamh argument) and if this program is used as a
|
||||
* model for anything, I should wish that you will take this error into
|
||||
* account.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
/* ------ some local (static) functions ------- */
|
||||
|
||||
static void bail_out(pam_handle_t *pamh, int really, int code, const char *fn)
|
||||
{
|
||||
fprintf(stderr,"==> called %s()\n got: `%s'\n", fn,
|
||||
pam_strerror(pamh, code));
|
||||
if (really && code)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* ------ some static data objects ------- */
|
||||
|
||||
static struct pam_conv conv = {
|
||||
misc_conv,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ------- the application itself -------- */
|
||||
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
pam_handle_t *pamh=NULL;
|
||||
char *username=NULL;
|
||||
int retcode;
|
||||
|
||||
/* did the user call with a username as an argument ? */
|
||||
|
||||
if (argc > 2) {
|
||||
fprintf(stderr,"usage: %s [username]\n",argv[0]);
|
||||
} else if (argc == 2) {
|
||||
username = argv[1];
|
||||
}
|
||||
|
||||
/* initialize the Linux-PAM library */
|
||||
retcode = pam_start("blank", username, &conv, &pamh);
|
||||
bail_out(pamh,1,retcode,"pam_start");
|
||||
|
||||
/* test the environment stuff */
|
||||
{
|
||||
#define MAXENV 15
|
||||
const char *greek[MAXENV] = {
|
||||
"a=alpha", "b=beta", "c=gamma", "d=delta", "e=epsilon",
|
||||
"f=phi", "g=psi", "h=eta", "i=iota", "j=mu", "k=nu",
|
||||
"l=zeta", "h=", "d", "k=xi"
|
||||
};
|
||||
char **env;
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAXENV; ++i) {
|
||||
retcode = pam_putenv(pamh,greek[i]);
|
||||
bail_out(pamh,0,retcode,"pam_putenv");
|
||||
}
|
||||
env = pam_getenvlist(pamh);
|
||||
if (env)
|
||||
env = pam_misc_drop_env(env);
|
||||
else
|
||||
fprintf(stderr,"???\n");
|
||||
fprintf(stderr,"a test: c=[%s], j=[%s]\n"
|
||||
, pam_getenv(pamh, "c"), pam_getenv(pamh, "j"));
|
||||
}
|
||||
|
||||
/* to avoid using goto we abuse a loop here */
|
||||
for (;;) {
|
||||
/* authenticate the user --- `0' here, could have been PAM_SILENT
|
||||
* | PAM_DISALLOW_NULL_AUTHTOK */
|
||||
|
||||
retcode = pam_authenticate(pamh, 0);
|
||||
bail_out(pamh,0,retcode,"pam_authenticate");
|
||||
|
||||
/* has the user proved themself valid? */
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: invalid request\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* the user is valid, but should they have access at this
|
||||
time? */
|
||||
|
||||
retcode = pam_acct_mgmt(pamh, 0); /* `0' could be as above */
|
||||
bail_out(pamh,0,retcode,"pam_acct_mgmt");
|
||||
|
||||
if (retcode == PAM_NEW_AUTHTOK_REQD) {
|
||||
fprintf(stderr,"Application must request new password...\n");
|
||||
retcode = pam_chauthtok(pamh,PAM_CHANGE_EXPIRED_AUTHTOK);
|
||||
bail_out(pamh,0,retcode,"pam_chauthtok");
|
||||
}
|
||||
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: invalid request\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* `0' could be as above */
|
||||
retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
|
||||
bail_out(pamh,0,retcode,"pam_setcred1");
|
||||
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: problem setting user credentials\n"
|
||||
,argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* open a session for the user --- `0' could be PAM_SILENT */
|
||||
retcode = pam_open_session(pamh,0);
|
||||
bail_out(pamh,0,retcode,"pam_open_session");
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: problem opening a session\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr,"The user has been authenticated and `logged in'\n");
|
||||
|
||||
/* close a session for the user --- `0' could be PAM_SILENT
|
||||
* it is possible that this pam_close_call is in another program..
|
||||
*/
|
||||
|
||||
retcode = pam_close_session(pamh,0);
|
||||
bail_out(pamh,0,retcode,"pam_close_session");
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: problem closing a session\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
retcode = pam_setcred(pamh, PAM_DELETE_CRED);
|
||||
bail_out(pamh,0,retcode,"pam_setcred2");
|
||||
|
||||
break; /* don't go on for ever! */
|
||||
}
|
||||
|
||||
/* close the Linux-PAM library */
|
||||
retcode = pam_end(pamh, PAM_SUCCESS);
|
||||
pamh = NULL;
|
||||
|
||||
bail_out(pamh,1,retcode,"pam_end");
|
||||
|
||||
exit(0);
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
$Id: check_user.c,v 1.1 1996/11/10 21:19:30 morgan Exp morgan $
|
||||
|
||||
This program was contributed by Shane Watts <shane@icarus.bofh.asn.au>
|
||||
slight modifications by AGM.
|
||||
|
||||
You need to add the following (or equivalent) to the /etc/pam.conf file.
|
||||
# check authorization
|
||||
check auth required pam_unix_auth.so
|
||||
check account required pam_unix_acct.so
|
||||
|
||||
$Log: check_user.c,v $
|
||||
Revision 1.1 1996/11/10 21:19:30 morgan
|
||||
Initial revision
|
||||
|
||||
*/
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static struct pam_conv conv = {
|
||||
misc_conv,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
pam_handle_t *pamh=NULL;
|
||||
int retval;
|
||||
const char *user="nobody";
|
||||
|
||||
if(argc == 2) {
|
||||
user = argv[1];
|
||||
}
|
||||
|
||||
if(argc > 2) {
|
||||
fprintf(stderr, "Usage: check_user [username]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
retval = pam_start("check", user, &conv, &pamh);
|
||||
|
||||
if (retval == PAM_SUCCESS)
|
||||
retval = pam_authenticate(pamh, 0); /* is user really user? */
|
||||
|
||||
if (retval == PAM_SUCCESS)
|
||||
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
|
||||
|
||||
/* This is where we have been authorized or not. */
|
||||
|
||||
if (retval == PAM_SUCCESS) {
|
||||
fprintf(stdout, "Authenticated\n");
|
||||
} else {
|
||||
fprintf(stdout, "Not Authenticated\n");
|
||||
}
|
||||
|
||||
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
|
||||
pamh = NULL;
|
||||
fprintf(stderr, "check_user: failed to release authenticator\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* $Log: test.c,v $
|
||||
* Revision 1.3 1996/03/10 00:14:20 morgan
|
||||
* made lines less than 80 chars long.
|
||||
*
|
||||
* Revision 1.2 1996/03/09 09:16:26 morgan
|
||||
* changed the header file that it includes.
|
||||
*
|
||||
* Revision 1.1 1996/03/09 09:13:34 morgan
|
||||
* Initial revision
|
||||
*/
|
||||
|
||||
/* Marc Ewing (marc@redhat.com) - original test code
|
||||
* Alexander O. Yuriev (alex@bach.cis.temple.edu)
|
||||
* Andrew Morgan (morgan@physics.ucla.edu)
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
/* this program is not written to the PAM spec: it tests the
|
||||
* pam_[sg]et_data() functions. Which is usually reserved for modules */
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
#define USERNAMESIZE 1024
|
||||
|
||||
static int test_conv( int num_msg,
|
||||
const struct pam_message **msgm,
|
||||
struct pam_response **response,
|
||||
void *appdata_ptr )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pam_conv conv = {
|
||||
test_conv,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int cleanup_func(pam_handle_t *pamh, void *data, int error_status)
|
||||
{
|
||||
printf("Cleaning up!\n");
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
void main( void )
|
||||
{
|
||||
pam_handle_t *pamh;
|
||||
char *name = ( char *) malloc( USERNAMESIZE + 1 );
|
||||
char *p = NULL;
|
||||
char *s = NULL;
|
||||
|
||||
if (! name )
|
||||
{
|
||||
perror( "Ouch, don't have enough memory");
|
||||
exit( -1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
fprintf( stdout, "Enter a name of a user to authenticate : ");
|
||||
name = fgets( name , USERNAMESIZE, stdin );
|
||||
if ( !name )
|
||||
{
|
||||
perror ( "Hey, how can authenticate "
|
||||
"someone whos name I don't know?" );
|
||||
exit ( -1 );
|
||||
}
|
||||
|
||||
*( name + strlen ( name ) - 1 ) = 0;
|
||||
|
||||
pam_start( "login", name, &conv, &pamh );
|
||||
|
||||
p = x_strdup( getpass ("Password: ") );
|
||||
if ( !p )
|
||||
{
|
||||
perror ( "You love NULL pointers, "
|
||||
"don't you? I don't ");
|
||||
exit ( -1 );
|
||||
}
|
||||
pam_set_item ( pamh, PAM_AUTHTOK, p );
|
||||
pam_get_item ( pamh, PAM_USER, (void**) &s);
|
||||
pam_set_data(pamh, "DATA", "Hi there! I'm data!", cleanup_func);
|
||||
pam_get_data(pamh, "DATA", (void **) &s);
|
||||
printf("%s\n", s);
|
||||
|
||||
fprintf( stdout, "*** Attempting to perform "
|
||||
"PAM authentication...\n");
|
||||
fprintf( stdout, "%s\n",
|
||||
pam_strerror( pam_authenticate( pamh, 0 ) ) ) ;
|
||||
|
||||
pam_end(pamh, PAM_SUCCESS);
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
static int test_conv(int num_msg, const struct pam_message **msgm,
|
||||
struct pam_response **response, void *appdata_ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pam_conv conv = {
|
||||
test_conv,
|
||||
NULL
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *user;
|
||||
pam_handle_t *pamh;
|
||||
struct passwd *pw;
|
||||
uid_t uid;
|
||||
int res;
|
||||
|
||||
uid = geteuid();
|
||||
pw = getpwuid(uid);
|
||||
if (pw) {
|
||||
user = pw->pw_name;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid userid: %d\n", uid);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pam_start("vpass", user, &conv, &pamh);
|
||||
pam_set_item(pamh, PAM_TTY, "/dev/tty");
|
||||
if ((res = pam_authenticate(pamh, 0)) != PAM_SUCCESS) {
|
||||
fprintf(stderr, "Oops: %s\n", pam_strerror(res));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pam_end(pamh, res);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
* $Id: xsh.c,v 1.4 1996/11/10 21:09:45 morgan Exp morgan $
|
||||
*
|
||||
* $Log: xsh.c,v $
|
||||
* Revision 1.4 1996/11/10 21:09:45 morgan
|
||||
* no gcc warnings
|
||||
*
|
||||
* Revision 1.3 1996/07/07 23:53:36 morgan
|
||||
* added support for non standard pam_fail_delay
|
||||
*
|
||||
* Revision 1.2 1996/05/02 04:44:48 morgan
|
||||
* moved conversaation to a libmisc routine.
|
||||
*
|
||||
* Revision 1.1 1996/04/07 08:18:55 morgan
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
|
||||
/* Andrew Morgan (morgan@parc.power.net) -- an example application
|
||||
* that invokes a shell, based on blank.c */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <security/pam_appl.h>
|
||||
#include <security/pam_misc.h>
|
||||
|
||||
/* ------ some local (static) functions ------- */
|
||||
|
||||
static void bail_out(pam_handle_t *pamh,int really, int code, const char *fn)
|
||||
{
|
||||
fprintf(stderr,"==> called %s()\n got: `%s'\n", fn,
|
||||
pam_strerror(pamh,code));
|
||||
if (really && code)
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* ------ some static data objects ------- */
|
||||
|
||||
static struct pam_conv conv = {
|
||||
misc_conv,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ------- the application itself -------- */
|
||||
|
||||
void main(int argc, char **argv, char **envp)
|
||||
{
|
||||
pam_handle_t *pamh=NULL;
|
||||
char *username=NULL;
|
||||
int retcode;
|
||||
|
||||
/* did the user call with a username as an argument ? */
|
||||
|
||||
if (argc > 2) {
|
||||
fprintf(stderr,"usage: %s [username]\n",argv[0]);
|
||||
} else if (argc == 2) {
|
||||
username = argv[1];
|
||||
}
|
||||
|
||||
/* initialize the Linux-PAM library */
|
||||
retcode = pam_start("xsh", username, &conv, &pamh);
|
||||
bail_out(pamh,1,retcode,"pam_start");
|
||||
|
||||
/* to avoid using goto we abuse a loop here */
|
||||
for (;;) {
|
||||
/* authenticate the user --- `0' here, could have been PAM_SILENT
|
||||
* | PAM_DISALLOW_NULL_AUTHTOK */
|
||||
|
||||
retcode = pam_authenticate(pamh, 0);
|
||||
bail_out(pamh,0,retcode,"pam_authenticate");
|
||||
|
||||
/* has the user proved themself valid? */
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: invalid request\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* the user is valid, but should they have access at this
|
||||
time? */
|
||||
|
||||
retcode = pam_acct_mgmt(pamh, 0); /* `0' could be as above */
|
||||
bail_out(pamh,0,retcode,"pam_acct_mgmt");
|
||||
|
||||
if (retcode == PAM_NEW_AUTHTOK_REQD) {
|
||||
fprintf(stderr,"Application must request new password...\n");
|
||||
retcode = pam_chauthtok(pamh,PAM_CHANGE_EXPIRED_AUTHTOK);
|
||||
bail_out(pamh,0,retcode,"pam_chauthtok");
|
||||
}
|
||||
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: invalid request\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* `0' could be as above */
|
||||
retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
|
||||
bail_out(pamh,0,retcode,"pam_setcred");
|
||||
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: problem setting user credentials\n"
|
||||
,argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* open a session for the user --- `0' could be PAM_SILENT */
|
||||
retcode = pam_open_session(pamh,0);
|
||||
bail_out(pamh,0,retcode,"pam_open_session");
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: problem opening a session\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr,"The user has been authenticated and `logged in'\n");
|
||||
|
||||
/* this is always a really bad thing for security! */
|
||||
system("/bin/sh");
|
||||
|
||||
/* close a session for the user --- `0' could be PAM_SILENT
|
||||
* it is possible that this pam_close_call is in another program..
|
||||
*/
|
||||
|
||||
retcode = pam_close_session(pamh,0);
|
||||
bail_out(pamh,0,retcode,"pam_close_session");
|
||||
if (retcode != PAM_SUCCESS) {
|
||||
fprintf(stderr,"%s: problem closing a session\n",argv[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
break; /* don't go on for ever! */
|
||||
}
|
||||
|
||||
/* close the Linux-PAM library */
|
||||
retcode = pam_end(pamh, PAM_SUCCESS);
|
||||
pamh = NULL;
|
||||
bail_out(pamh,1,retcode,"pam_end");
|
||||
|
||||
exit(0);
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
# $Id: Makefile,v 1.21 1997/04/05 06:44:43 morgan Exp morgan $
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# This makefile controls the build process of shared and static PAM modules.
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.21 1997/04/05 06:44:43 morgan
|
||||
# pam_env and pam_tally added
|
||||
#
|
||||
# Revision 1.20 1997/02/15 18:57:11 morgan
|
||||
# fixed bash syntax
|
||||
#
|
||||
# Revision 1.19 1997/01/04 20:21:32 morgan
|
||||
# moved responsibility of conditional compilation to modules (more flexible)
|
||||
#
|
||||
# Revision 1.18 1996/12/01 03:34:40 morgan
|
||||
# update for .54
|
||||
#
|
||||
# Revision 1.17 1996/11/10 20:20:15 morgan
|
||||
# cross platform support and new modules
|
||||
#
|
||||
# Revision 1.16 1996/09/05 06:20:45 morgan
|
||||
# added two modules: listfile and shells
|
||||
#
|
||||
# Revision 1.15 1996/08/09 05:38:28 morgan
|
||||
# added new/proposed modules.
|
||||
# fixed makefile installation dependencies
|
||||
#
|
||||
# Revision 1.14 1996/07/08 00:00:33 morgan
|
||||
# added wheel and group modules
|
||||
#
|
||||
|
||||
MODDIRS=\
|
||||
pam_access \
|
||||
pam_afs \
|
||||
pam_afsauth \
|
||||
pam_afspass \
|
||||
pam_afstok \
|
||||
pam_cracklib \
|
||||
pam_deny \
|
||||
pam_desgold \
|
||||
pam_env \
|
||||
pam_filter \
|
||||
pam_ftp \
|
||||
pam_group \
|
||||
pam_kerberos \
|
||||
pam_krb4 \
|
||||
pam_lastlog \
|
||||
pam_listfile \
|
||||
pam_limits \
|
||||
pam_mail \
|
||||
pam_nologin \
|
||||
pam_opie \
|
||||
pam_passwd+ \
|
||||
pam_permit \
|
||||
pam_pwdb \
|
||||
pam_radius \
|
||||
pam_restrict \
|
||||
pam_rhosts \
|
||||
pam_rootok \
|
||||
pam_securetty \
|
||||
pam_shells \
|
||||
pam_sid \
|
||||
pam_skey \
|
||||
pam_skey2 \
|
||||
pam_stress \
|
||||
pam_syslog \
|
||||
pam_tally \
|
||||
pam_time \
|
||||
pam_unix \
|
||||
pam_warn \
|
||||
pam_wheel
|
||||
|
||||
|
||||
# ////////////////////////////////////////////////////
|
||||
# // You should not modify anything below this line //
|
||||
# ////////////////////////////////////////////////////
|
||||
|
||||
dummy:
|
||||
@echo "*** This is not a top-level Makefile! ***"
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
all:
|
||||
@echo modules for $(OS) are:
|
||||
@ls -d $(MODDIRS) 2>/dev/null ; echo :--------
|
||||
@echo
|
||||
ifdef STATIC
|
||||
rm -f ./_static_module_*
|
||||
endif
|
||||
@for i in $(MODDIRS) ; do \
|
||||
if [ -d $$i ]; then { \
|
||||
$(MAKE) -C $$i all ; \
|
||||
if [ $$? -ne 0 ]; then exit 1 ; fi ; \
|
||||
} elif [ -f ./.$$i ]; then { \
|
||||
cat ./.$$i ; \
|
||||
} fi ; \
|
||||
done
|
||||
|
||||
install:
|
||||
for i in $(MODDIRS) ; do \
|
||||
if [ -d $$i ]; then { \
|
||||
$(MAKE) -C $$i install ; \
|
||||
if [ $$? -ne 0 ]; then exit 1 ; fi ; \
|
||||
} fi ; \
|
||||
done
|
||||
|
||||
remove:
|
||||
for i in $(MODDIRS) ; do \
|
||||
if [ -d $$i ]; then { \
|
||||
$(MAKE) -C $$i remove ; \
|
||||
} fi ; \
|
||||
done
|
||||
|
||||
lclean:
|
||||
rm -f _static_module_*
|
||||
|
||||
clean: lclean
|
||||
for i in $(MODDIRS) ; do \
|
||||
if [ -d $$i ]; then { \
|
||||
$(MAKE) -C $$i clean ; \
|
||||
} fi ; \
|
||||
done
|
||||
|
||||
extraclean: lclean
|
||||
for i in $(MODDIRS) ; do \
|
||||
if [ -d $$i ]; then \
|
||||
$(MAKE) -C $$i extraclean ; \
|
||||
fi ; \
|
||||
done
|
||||
|
@ -1,55 +0,0 @@
|
||||
This directory contains the modules.
|
||||
|
||||
If you want to reserve a module name please email <pam-list@redhat.com>
|
||||
and announce its name. Andrew Morgan, <morgan@parc.power.net>, will
|
||||
add it to the Makefile in the next release of Linux-PAM.
|
||||
|
||||
As of Linux-PAM-0.40 modules can optionally conform to the static
|
||||
modules conventions.
|
||||
|
||||
This file was updated for Linux-PAM-0.53.
|
||||
|
||||
The conventions are as follows:
|
||||
|
||||
There are only 6 functions that a module may declare as "public" they
|
||||
fall into 4 managment groups as follows:
|
||||
|
||||
functions Management group
|
||||
------------------------------------------ ----------------
|
||||
pam_sm_authenticate, pam_sm_setcred, PAM_SM_AUTH
|
||||
pam_sm_acct_mgmt, PAM_SM_ACCOUNT
|
||||
pam_sm_open_session, pam_sm_close_session, PAM_SM_SESSION
|
||||
pam_sm_chauthtok PAM_SM_PASSWORD
|
||||
|
||||
If a module contains definitions for any of the above functions, it
|
||||
must supply definitions for all of the functions in the corresponding
|
||||
management group.
|
||||
|
||||
The header file that defines the ANSI prototypes for these functions
|
||||
is <security/pam_modules.h> . In the case that the module wishes to
|
||||
offer the functions of a given managment group, it must #define
|
||||
PAM_SM_XXX, where XXX is one of the above four tokens. These
|
||||
definitions must occur *prior* to the
|
||||
#include <security/pam_modules.h> line.
|
||||
|
||||
The pam_sm_... functions should be defined to be of type 'PAM_EXTERN int'.
|
||||
|
||||
In the case that a module is being compiled with PAM_STATIC #define'd
|
||||
it should also define a globally accessible structure
|
||||
_"NAME"_modstruct containing references to each of the functions
|
||||
defined by the module. (this structure is defined in
|
||||
<security/pam_modules.h>. "NAME" is the title of the module
|
||||
(eg. "pam_deny")
|
||||
|
||||
If a module wants to be included in the static libpam.a its Makefile
|
||||
should execute "register_static" with appropriate arguments (in this
|
||||
directory).
|
||||
|
||||
[
|
||||
For SIMPLE working examples, see
|
||||
|
||||
./modules/pam_deny/* and ./modules/pam_rootok/*
|
||||
.]
|
||||
|
||||
Andrew Morgan
|
||||
96/11/10
|
@ -1,19 +0,0 @@
|
||||
#########################################################################
|
||||
# This is a makefile that does nothing. It is designed to be included
|
||||
# by module Makefile-s when they are not compatable with the local
|
||||
# system
|
||||
#########################################################################
|
||||
|
||||
all:
|
||||
@echo "This module will not be compiled on this system"
|
||||
|
||||
extraclean: clean
|
||||
|
||||
install: clean
|
||||
|
||||
clean:
|
||||
@echo "Nothing to do"
|
||||
|
||||
#########################################################################
|
||||
# all over..
|
||||
#########################################################################
|
@ -1,111 +0,0 @@
|
||||
# $Id: Makefile,v 1.1 1997/06/23 00:39:42 morgan Exp morgan $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.1 1997/06/23 00:39:42 morgan
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
|
||||
TITLE=pam_access
|
||||
CONFD=$(CONFIGED)/security
|
||||
export CONFD
|
||||
CONFILE=$(CONFD)/access.conf
|
||||
export CONFILE
|
||||
|
||||
# Convenient defaults for compiling independently of the full source
|
||||
# tree.
|
||||
ifndef FULL_LINUX_PAM_SOURCE_TREE
|
||||
export DYNAMIC=-DPAM_DYNAMIC
|
||||
export CC=gcc
|
||||
export CFLAGS=-O2 -Dlinux -DLINUX_PAM \
|
||||
-ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \
|
||||
-Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \
|
||||
-Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \
|
||||
-Wshadow -pedantic -fPIC
|
||||
export MKDIR=mkdir -p
|
||||
export LD_D=gcc -shared -Xlinker -x
|
||||
endif
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
DEFS=-DCONFILE=\"$(CONFILE)\"
|
||||
|
||||
CFLAGS += $(DEFS)
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
$(MKDIR) $(FAKEROOT)$(SCONFIGED)
|
||||
bash -f ./install_conf
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
rm -f $(FAKEROOT)$(CONFILE)
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
rm -f ./.ignore_age
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
@ -1,40 +0,0 @@
|
||||
# Description of its configuration file (/etc/security/access.conf):
|
||||
#
|
||||
# Login access control table.
|
||||
#
|
||||
# When someone logs in, the table is scanned for the first entry that
|
||||
# matches the (user, host) combination, or, in case of non-networked
|
||||
# logins, the first entry that matches the (user, tty) combination. The
|
||||
# permissions field of that table entry determines whether the login will
|
||||
# be accepted or refused.
|
||||
#
|
||||
# Format of the login access control table is three fields separated by a
|
||||
# ":" character:
|
||||
#
|
||||
# permission : users : origins
|
||||
#
|
||||
# The first field should be a "+" (access granted) or "-" (access denied)
|
||||
# character.
|
||||
#
|
||||
# The second field should be a list of one or more login names, group
|
||||
# names, or ALL (always matches). A pattern of the form user@host is
|
||||
# matched when the login name matches the "user" part, and when the
|
||||
# "host" part matches the local machine name.
|
||||
#
|
||||
# The third field should be a list of one or more tty names (for
|
||||
# non-networked logins), host names, domain names (begin with "."), host
|
||||
# addresses, internet network numbers (end with "."), ALL (always
|
||||
# matches) or LOCAL (matches any string that does not contain a "."
|
||||
# character).
|
||||
#
|
||||
# If you run NIS you can use @netgroupname in host or user patterns; this
|
||||
# even works for @usergroup@@hostgroup patterns. Weird.
|
||||
#
|
||||
# The EXCEPT operator makes it possible to write very compact rules.
|
||||
#
|
||||
# The group file is searched only when a name does not match that of the
|
||||
# logged-in user. Both the user's primary group is matched, as well as
|
||||
# groups in which users are explicitly listed.
|
||||
#
|
||||
# Alexei Nogin <alexei@nogin.dnttm.ru> 1997/06/15
|
||||
############################################################################
|
@ -1,52 +0,0 @@
|
||||
# Login access control table.
|
||||
#
|
||||
# When someone logs in, the table is scanned for the first entry that
|
||||
# matches the (user, host) combination, or, in case of non-networked
|
||||
# logins, the first entry that matches the (user, tty) combination. The
|
||||
# permissions field of that table entry determines whether the login will
|
||||
# be accepted or refused.
|
||||
#
|
||||
# Format of the login access control table is three fields separated by a
|
||||
# ":" character:
|
||||
#
|
||||
# permission : users : origins
|
||||
#
|
||||
# The first field should be a "+" (access granted) or "-" (access denied)
|
||||
# character.
|
||||
#
|
||||
# The second field should be a list of one or more login names, group
|
||||
# names, or ALL (always matches). A pattern of the form user@host is
|
||||
# matched when the login name matches the "user" part, and when the
|
||||
# "host" part matches the local machine name.
|
||||
#
|
||||
# The third field should be a list of one or more tty names (for
|
||||
# non-networked logins), host names, domain names (begin with "."), host
|
||||
# addresses, internet network numbers (end with "."), ALL (always
|
||||
# matches) or LOCAL (matches any string that does not contain a "."
|
||||
# character).
|
||||
#
|
||||
# If you run NIS you can use @netgroupname in host or user patterns; this
|
||||
# even works for @usergroup@@hostgroup patterns. Weird.
|
||||
#
|
||||
# The EXCEPT operator makes it possible to write very compact rules.
|
||||
#
|
||||
# The group file is searched only when a name does not match that of the
|
||||
# logged-in user. Both the user's primary group is matched, as well as
|
||||
# groups in which users are explicitly listed.
|
||||
#
|
||||
##############################################################################
|
||||
#
|
||||
# Disallow console logins to all but a few accounts.
|
||||
#
|
||||
#-:ALL EXCEPT wheel shutdown sync:console
|
||||
#
|
||||
# Disallow non-local logins to privileged accounts (group wheel).
|
||||
#
|
||||
#-:wheel:ALL EXCEPT LOCAL .win.tue.nl
|
||||
#
|
||||
# Some accounts are not allowed to login from anywhere:
|
||||
#
|
||||
#-:wsbscaro wsbsecr wsbspac wsbsym wscosor wstaiwde:ALL
|
||||
#
|
||||
# All other accounts are allowed to login from anywhere.
|
||||
#
|
@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFILE=$FAKEROOT"$CONFILE"
|
||||
IGNORE_AGE=./.ignore_age
|
||||
CONF=./access.conf
|
||||
QUIET_INSTALL=../../.quiet_install
|
||||
MODULE=pam_access
|
||||
|
||||
echo
|
||||
|
||||
if [ -f "$QUIET_INSTALL" ]; then
|
||||
if [ ! -f "$CONFILE" ]; then
|
||||
yes="y"
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
elif [ -f "$IGNORE_AGE" ]; then
|
||||
echo "you don't want to be bothered with the age of your $CONFILE file"
|
||||
yes="n"
|
||||
elif [ ! -f "$CONFILE" ] || [ "$CONF" -nt "$CONFILE" ]; then
|
||||
if [ -f "$CONFILE" ]; then
|
||||
echo "An older $MODULE configuration file already exists ($CONFILE)"
|
||||
echo "Do you wish to copy the $CONF file in this distribution"
|
||||
echo "to $CONFILE ? (y/n) [skip] "
|
||||
read yes
|
||||
else
|
||||
yes="y"
|
||||
fi
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
|
||||
if [ "$yes" = "y" ]; then
|
||||
mkdir -p $FAKEROOT$CONFD
|
||||
echo " copying $CONF to $CONFILE"
|
||||
cp $CONF $CONFILE
|
||||
else
|
||||
echo " Skipping $CONF installation"
|
||||
if [ "$yes" = "n" ]; then
|
||||
touch "$IGNORE_AGE"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
@ -1,424 +0,0 @@
|
||||
/* pam_access module */
|
||||
|
||||
/*
|
||||
* Written by Alexei Nogin <alexei@nogin.dnttm.ru> 1997/06/15
|
||||
* (I took login_access from logdaemon-5.6 and converted it to PAM
|
||||
* using parts of pam_time code.)
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
# define _GNU_SOURCE
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
/* man page says above file includes this... */
|
||||
extern int gethostname(char *name, size_t len);
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#ifndef BROKEN_NETWORK_MATCH
|
||||
# include <netdb.h>
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* here, we make definitions for the externally accessible functions
|
||||
* in this file (these definitions are required for static modules
|
||||
* but strongly encouraged generally) they are used to instruct the
|
||||
* modules include file to define their prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_ACCOUNT
|
||||
|
||||
#include <security/_pam_macros.h>
|
||||
#include <security/pam_modules.h>
|
||||
|
||||
/* --- static functions for checking whether the user should be let in --- */
|
||||
|
||||
static void _log_err(const char *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("pam_access", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(LOG_ERR, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
#define PAM_ACCESS_CONFIG CONFILE
|
||||
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
|
||||
/* login_access.c from logdaemon-5.6 with several changes by A.Nogin: */
|
||||
|
||||
/*
|
||||
* This module implements a simple but effective form of login access
|
||||
* control based on login names and on host (or domain) names, internet
|
||||
* addresses (or network numbers), or on terminal line names in case of
|
||||
* non-networked logins. Diagnostics are reported through syslog(3).
|
||||
*
|
||||
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
|
||||
*/
|
||||
|
||||
#if !defined(MAXHOSTNAMELEN) || (MAXHOSTNAMELEN < 64)
|
||||
#undef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 256
|
||||
#endif
|
||||
|
||||
/* Delimiters for fields and for lists of users, ttys or hosts. */
|
||||
|
||||
static char fs[] = ":"; /* field separator */
|
||||
static char sep[] = ", \t"; /* list-element separator */
|
||||
|
||||
/* Constants to be used in assignments only, not in comparisons... */
|
||||
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
|
||||
/*
|
||||
* A structure to bundle up all login-related information to keep the
|
||||
* functional interfaces as generic as possible.
|
||||
*/
|
||||
struct login_info {
|
||||
struct passwd *user;
|
||||
char *from;
|
||||
};
|
||||
|
||||
typedef int match_func (char *, struct login_info *);
|
||||
|
||||
static int list_match (char *, struct login_info *,
|
||||
match_func *);
|
||||
static int user_match (char *, struct login_info *);
|
||||
static int from_match (char *, struct login_info *);
|
||||
static int string_match (char *, char *);
|
||||
|
||||
/* login_access - match username/group and host/tty with access control file */
|
||||
|
||||
static int login_access(struct passwd *user, char *from)
|
||||
{
|
||||
struct login_info item;
|
||||
FILE *fp;
|
||||
char line[BUFSIZ];
|
||||
char *perm; /* becomes permission field */
|
||||
char *users; /* becomes list of login names */
|
||||
char *froms; /* becomes list of terminals or hosts */
|
||||
int match = NO;
|
||||
int end;
|
||||
int lineno = 0; /* for diagnostics */
|
||||
|
||||
/*
|
||||
* Bundle up the arguments to avoid unnecessary clumsiness lateron.
|
||||
*/
|
||||
item.user = user;
|
||||
item.from = from;
|
||||
|
||||
/*
|
||||
* Process the table one line at a time and stop at the first match.
|
||||
* Blank lines and lines that begin with a '#' character are ignored.
|
||||
* Non-comment lines are broken at the ':' character. All fields are
|
||||
* mandatory. The first field should be a "+" or "-" character. A
|
||||
* non-existing table means no access control.
|
||||
*/
|
||||
|
||||
if ((fp = fopen(PAM_ACCESS_CONFIG, "r"))!=NULL) {
|
||||
while (!match && fgets(line, sizeof(line), fp)) {
|
||||
lineno++;
|
||||
if (line[end = strlen(line) - 1] != '\n') {
|
||||
_log_err("%s: line %d: missing newline or line too long",
|
||||
PAM_ACCESS_CONFIG, lineno);
|
||||
continue;
|
||||
}
|
||||
if (line[0] == '#')
|
||||
continue; /* comment line */
|
||||
while (end > 0 && isspace(line[end - 1]))
|
||||
end--;
|
||||
line[end] = 0; /* strip trailing whitespace */
|
||||
if (line[0] == 0) /* skip blank lines */
|
||||
continue;
|
||||
if (!(perm = strtok(line, fs))
|
||||
|| !(users = strtok((char *) 0, fs))
|
||||
|| !(froms = strtok((char *) 0, fs))
|
||||
|| strtok((char *) 0, fs)) {
|
||||
_log_err("%s: line %d: bad field count", PAM_ACCESS_CONFIG, lineno);
|
||||
continue;
|
||||
}
|
||||
if (perm[0] != '+' && perm[0] != '-') {
|
||||
_log_err("%s: line %d: bad first field", PAM_ACCESS_CONFIG, lineno);
|
||||
continue;
|
||||
}
|
||||
match = (list_match(froms, &item, from_match)
|
||||
&& list_match(users, &item, user_match));
|
||||
}
|
||||
(void) fclose(fp);
|
||||
} else if (errno != ENOENT) {
|
||||
_log_err("cannot open %s: %m", PAM_ACCESS_CONFIG);
|
||||
}
|
||||
return (match == 0 || (line[0] == '+'));
|
||||
}
|
||||
|
||||
/* list_match - match an item against a list of tokens with exceptions */
|
||||
|
||||
static int list_match(char *list, struct login_info *item, match_func *match_fn)
|
||||
{
|
||||
char *tok;
|
||||
int match = NO;
|
||||
|
||||
/*
|
||||
* Process tokens one at a time. We have exhausted all possible matches
|
||||
* when we reach an "EXCEPT" token or the end of the list. If we do find
|
||||
* a match, look for an "EXCEPT" list and recurse to determine whether
|
||||
* the match is affected by any exceptions.
|
||||
*/
|
||||
|
||||
for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
|
||||
if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
|
||||
break;
|
||||
if ((match = (*match_fn) (tok, item))) /* YES */
|
||||
break;
|
||||
}
|
||||
/* Process exceptions to matches. */
|
||||
|
||||
if (match != NO) {
|
||||
while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
|
||||
/* VOID */ ;
|
||||
if (tok == 0 || list_match((char *) 0, item, match_fn) == NO)
|
||||
return (match);
|
||||
}
|
||||
return (NO);
|
||||
}
|
||||
|
||||
/* myhostname - figure out local machine name */
|
||||
|
||||
static char * myhostname(void)
|
||||
{
|
||||
static char name[MAXHOSTNAMELEN + 1];
|
||||
|
||||
gethostname(name, MAXHOSTNAMELEN);
|
||||
name[MAXHOSTNAMELEN] = 0;
|
||||
return (name);
|
||||
}
|
||||
|
||||
/* netgroup_match - match group against machine or user */
|
||||
|
||||
static int netgroup_match(char *group, char *machine, char *user)
|
||||
{
|
||||
#ifdef NIS
|
||||
static char *mydomain = 0;
|
||||
|
||||
if (mydomain == 0)
|
||||
yp_get_default_domain(&mydomain);
|
||||
return (innetgr(group, machine, user, mydomain));
|
||||
#else
|
||||
_log_err("NIS netgroup support not configured");
|
||||
return (NO);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* user_match - match a username against one token */
|
||||
|
||||
static int user_match(char *tok, struct login_info *item)
|
||||
{
|
||||
char *string = item->user->pw_name;
|
||||
struct login_info fake_item;
|
||||
struct group *group;
|
||||
int i;
|
||||
char *at;
|
||||
|
||||
/*
|
||||
* If a token has the magic value "ALL" the match always succeeds.
|
||||
* Otherwise, return YES if the token fully matches the username, if the
|
||||
* token is a group that contains the username, or if the token is the
|
||||
* name of the user's primary group.
|
||||
*/
|
||||
|
||||
if ((at = strchr(tok + 1, '@')) != 0) { /* split user@host pattern */
|
||||
*at = 0;
|
||||
fake_item.from = myhostname();
|
||||
return (user_match(tok, item) && from_match(at + 1, &fake_item));
|
||||
} else if (tok[0] == '@') { /* netgroup */
|
||||
return (netgroup_match(tok + 1, (char *) 0, string));
|
||||
} else if (string_match(tok, string)) { /* ALL or exact match */
|
||||
return (YES);
|
||||
} else if ((group = getgrnam(tok))) { /* try group membership */
|
||||
if (item->user->pw_gid == group->gr_gid)
|
||||
return (YES);
|
||||
for (i = 0; group->gr_mem[i]; i++)
|
||||
if (strcasecmp(string, group->gr_mem[i]) == 0)
|
||||
return (YES);
|
||||
}
|
||||
return (NO);
|
||||
}
|
||||
|
||||
/* from_match - match a host or tty against a list of tokens */
|
||||
|
||||
static int from_match(char *tok, struct login_info *item)
|
||||
{
|
||||
char *string = item->from;
|
||||
int tok_len;
|
||||
int str_len;
|
||||
|
||||
/*
|
||||
* If a token has the magic value "ALL" the match always succeeds. Return
|
||||
* YES if the token fully matches the string. If the token is a domain
|
||||
* name, return YES if it matches the last fields of the string. If the
|
||||
* token has the magic value "LOCAL", return YES if the string does not
|
||||
* contain a "." character. If the token is a network number, return YES
|
||||
* if it matches the head of the string.
|
||||
*/
|
||||
|
||||
if (tok[0] == '@') { /* netgroup */
|
||||
return (netgroup_match(tok + 1, string, (char *) 0));
|
||||
} else if (string_match(tok, string)) { /* ALL or exact match */
|
||||
return (YES);
|
||||
} else if (tok[0] == '.') { /* domain: match last fields */
|
||||
if ((str_len = strlen(string)) > (tok_len = strlen(tok))
|
||||
&& strcasecmp(tok, string + str_len - tok_len) == 0)
|
||||
return (YES);
|
||||
} else if (strcasecmp(tok, "LOCAL") == 0) { /* local: no dots */
|
||||
if (strchr(string, '.') == 0)
|
||||
return (YES);
|
||||
#ifdef BROKEN_NETWORK_MATCH
|
||||
} else if (tok[(tok_len = strlen(tok)) - 1] == '.' /* network */
|
||||
&& strncmp(tok, string, tok_len) == 0) {
|
||||
return (YES);
|
||||
#else /* BROKEN_NETWORK_MATCH */
|
||||
} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {
|
||||
/*
|
||||
The code below does a more correct check if the address specified
|
||||
by "string" starts from "tok".
|
||||
1998/01/27 Andrey V. Savochkin <saw@msu.ru>
|
||||
*/
|
||||
struct hostent *h;
|
||||
char hn[3+1+3+1+3+1+3+1];
|
||||
int r;
|
||||
|
||||
h = gethostbyname(string);
|
||||
if (h == NULL)
|
||||
return (NO);
|
||||
if (h->h_addrtype != AF_INET)
|
||||
return (NO);
|
||||
if (h->h_length != 4)
|
||||
return (NO); /* only IPv4 addresses (SAW) */
|
||||
r = snprintf(hn, sizeof(hn), "%u.%u.%u.%u",
|
||||
(unsigned char)h->h_addr[0], (unsigned char)h->h_addr[1],
|
||||
(unsigned char)h->h_addr[2], (unsigned char)h->h_addr[3]);
|
||||
if (r < 0 || r >= sizeof(hn))
|
||||
return (NO);
|
||||
if (!strncmp(tok, hn, tok_len))
|
||||
return (YES);
|
||||
#endif /* BROKEN_NETWORK_MATCH */
|
||||
}
|
||||
return (NO);
|
||||
}
|
||||
|
||||
/* string_match - match a string against one token */
|
||||
|
||||
static int string_match(char *tok, char *string)
|
||||
{
|
||||
|
||||
/*
|
||||
* If the token has the magic value "ALL" the match always succeeds.
|
||||
* Otherwise, return YES if the token fully matches the string.
|
||||
*/
|
||||
|
||||
if (strcasecmp(tok, "ALL") == 0) { /* all: always matches */
|
||||
return (YES);
|
||||
} else if (strcasecmp(tok, string) == 0) { /* try exact match */
|
||||
return (YES);
|
||||
}
|
||||
return (NO);
|
||||
}
|
||||
|
||||
/* end of login_access.c */
|
||||
|
||||
int strcasecmp(const char *s1, const char *s2)
|
||||
{
|
||||
while ((toupper(*s1)==toupper(*s2)) && (*s1) && (*s2)) {s1++; s2++;}
|
||||
return(toupper(*s1)-toupper(*s2));
|
||||
}
|
||||
|
||||
/* --- public account management functions --- */
|
||||
|
||||
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
const char *user=NULL;
|
||||
char *from=NULL;
|
||||
struct passwd *user_pw;
|
||||
|
||||
/* set username */
|
||||
|
||||
if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL
|
||||
|| *user == '\0') {
|
||||
_log_err("cannot determine the user's name");
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
/* remote host name */
|
||||
|
||||
if (pam_get_item(pamh, PAM_RHOST, (const void **)&from)
|
||||
!= PAM_SUCCESS) {
|
||||
_log_err("cannot find the remote host name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
if (from==NULL) {
|
||||
|
||||
/* local login, set tty name */
|
||||
|
||||
if (pam_get_item(pamh, PAM_TTY, (const void **)&from) != PAM_SUCCESS
|
||||
|| from == NULL) {
|
||||
D(("PAM_TTY not set, probing stdin"));
|
||||
from = ttyname(STDIN_FILENO);
|
||||
if (from == NULL) {
|
||||
_log_err("couldn't get the tty name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
if (pam_set_item(pamh, PAM_TTY, from) != PAM_SUCCESS) {
|
||||
_log_err("couldn't set tty name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
}
|
||||
if (strncmp("/dev/",from,5) == 0) { /* strip leading /dev/ */
|
||||
from += 5;
|
||||
}
|
||||
|
||||
}
|
||||
if ((user_pw=getpwnam(user))==NULL) return (PAM_USER_UNKNOWN);
|
||||
if (login_access(user_pw,from)) return (PAM_SUCCESS); else {
|
||||
_log_err("access denied for user `%s' from `%s'",user,from);
|
||||
return (PAM_PERM_DENIED);
|
||||
}
|
||||
}
|
||||
|
||||
/* end of module definition */
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_access_modstruct = {
|
||||
"pam_access",
|
||||
NULL,
|
||||
NULL,
|
||||
pam_sm_acct_mgmt,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
@ -1,110 +0,0 @@
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# Created by Cristian Gafton <gafton@redhat.com> 1996/09/10
|
||||
#
|
||||
|
||||
ifndef FULL_LINUX_PAM_SOURCE_TREE
|
||||
#
|
||||
# here you should make default variable defines...
|
||||
#
|
||||
MKDIR=mkdir -p
|
||||
LD_D=gcc -shared -Xlinker -x
|
||||
INSTALL=install
|
||||
SECUREDIR=/usr/lib/security
|
||||
#
|
||||
HAVE_CRACKLIB=yes
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_CRACKLIB),yes)
|
||||
|
||||
TITLE=pam_cracklib
|
||||
CRACKLIB=-lcrack
|
||||
CRACKLIB_DICTPATH=/usr/lib/cracklib_dict
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
ifdef CRACKLIB_DICTPATH
|
||||
CFLAGS+=-DCRACKLIB_DICTPATH=\"$(CRACKLIB_DICTPATH)\"
|
||||
endif
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC) Makefile
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD) $(CRACKLIB)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak dynamic/* static/*
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
else
|
||||
|
||||
include ../dont_makefile
|
||||
|
||||
endif
|
@ -1,21 +0,0 @@
|
||||
|
||||
pam_cracklib:
|
||||
check the passwd against dictionary words.
|
||||
|
||||
RECOGNIZED ARGUMENTS:
|
||||
debug verbose log
|
||||
|
||||
type=XXX alter the message printed as a prompt to the user.
|
||||
the message printed is in the form
|
||||
"New XXX password: ".
|
||||
Default XXX=UNIX
|
||||
|
||||
retry=N Prompt user at most N times before returning with
|
||||
error. Default N=1.
|
||||
|
||||
MODULE SERVICES PROVIDED:
|
||||
passwd chauthtok
|
||||
|
||||
AUTHOR:
|
||||
Cristian Gafton <gafton@sorosis.ro>
|
||||
|
@ -1,687 +0,0 @@
|
||||
/* pam_cracklib module */
|
||||
|
||||
/*
|
||||
* 0.85. added six new options to use this with long passwords.
|
||||
* 0.8. tidied output and improved D(()) usage for debugging.
|
||||
* 0.7. added support for more obscure checks for new passwd.
|
||||
* 0.6. root can reset user passwd to any values (it's only warned)
|
||||
* 0.5. supports retries - 'retry=N' argument
|
||||
* 0.4. added argument 'type=XXX' for 'New XXX password' prompt
|
||||
* 0.3. Added argument 'debug'
|
||||
* 0.2. new password is feeded to cracklib for verify after typed once
|
||||
* 0.1. First release
|
||||
*/
|
||||
|
||||
/*
|
||||
* Written by Cristian Gafton <gafton@redhat.com> 1996/09/10
|
||||
* Long password support by Philip W. Dalrymple <pwd@mdtsoft.com> 1997/07/18
|
||||
* See the end of the file for Copyright Information
|
||||
*
|
||||
* Modification for long password systems (>8 chars). The original
|
||||
* module had problems when used in a md5 password system in that it
|
||||
* allowed too short passwords but required that at least half of the
|
||||
* bytes in the new password did not appear in the old one. this
|
||||
* action is still the default and the changes should not break any
|
||||
* current user. This modification adds 6 new options, one to set the
|
||||
* number of bytes in the new password that are not in the old one,
|
||||
* the other five to control the length checking, these are all
|
||||
* documented (or will be before anyone else sees this code) in the PAM
|
||||
* S.A.G. in the section on the cracklib module.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#define __USE_BSD
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
|
||||
extern char *FascistCheck(char *pw, const char *dictpath);
|
||||
|
||||
#ifndef CRACKLIB_DICTPATH
|
||||
#define CRACKLIB_DICTPATH "/usr/lib/cracklib_dict"
|
||||
#endif
|
||||
|
||||
#define PROMPT1 "New %s password: "
|
||||
#define PROMPT2 "Retype new %s password: "
|
||||
#define MISTYPED_PASS "Sorry, passwords do not match"
|
||||
|
||||
/*
|
||||
* here, we make a definition for the externally accessible function
|
||||
* in this file (this definition is required for static a module
|
||||
* but strongly encouraged generally) it is used to instruct the
|
||||
* modules include file to define the function prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_PASSWORD
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
#ifndef LINUX_PAM
|
||||
#include <security/pam_appl.h>
|
||||
#endif /* LINUX_PAM */
|
||||
|
||||
/* some syslogging */
|
||||
|
||||
static void _pam_log(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("PAM-Cracklib", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
/* argument parsing */
|
||||
#define PAM_DEBUG_ARG 0x0001
|
||||
|
||||
/* module data - AGM: please remove these static variables... PAM was
|
||||
* designed to be reentrant based soley on a unique pamh... this
|
||||
* breaks that. */
|
||||
|
||||
static int retry_times = 0;
|
||||
static int diff_ok = 10;
|
||||
static int min_length = 9;
|
||||
static int dig_credit = 1;
|
||||
static int up_credit = 1;
|
||||
static int low_credit = 1;
|
||||
static int oth_credit = 1;
|
||||
static char prompt_type[BUFSIZ];
|
||||
|
||||
static int _pam_parse(int argc, const char **argv)
|
||||
{
|
||||
int ctrl=0;
|
||||
|
||||
/* step through arguments */
|
||||
for (ctrl=0; argc-- > 0; ++argv) {
|
||||
char *ep = NULL;
|
||||
|
||||
/* generic options */
|
||||
|
||||
if (!strcmp(*argv,"debug"))
|
||||
ctrl |= PAM_DEBUG_ARG;
|
||||
else if (!strncmp(*argv,"type=",5))
|
||||
strcpy(prompt_type, *argv+5);
|
||||
else if (!strncmp(*argv,"retry=",6)) {
|
||||
retry_times = strtol(*argv+6,&ep,10);
|
||||
if (!ep || (retry_times < 1))
|
||||
retry_times = 1;
|
||||
} else if (!strncmp(*argv,"difok=",6)) {
|
||||
diff_ok = strtol(*argv+6,&ep,10);
|
||||
if (!ep || (diff_ok < 0))
|
||||
diff_ok = 10;
|
||||
} else if (!strncmp(*argv,"minlen=",7)) {
|
||||
min_length = strtol(*argv+7,&ep,10);
|
||||
if (!ep || (min_length < 5))
|
||||
min_length = 5;
|
||||
} else if (!strncmp(*argv,"dcredit=",8)) {
|
||||
dig_credit = strtol(*argv+8,&ep,10);
|
||||
if (!ep || (dig_credit < 0))
|
||||
dig_credit = 0;
|
||||
} else if (!strncmp(*argv,"ucredit=",8)) {
|
||||
up_credit = strtol(*argv+8,&ep,10);
|
||||
if (!ep || (up_credit < 0))
|
||||
up_credit = 0;
|
||||
} else if (!strncmp(*argv,"lcredit=",8)) {
|
||||
low_credit = strtol(*argv+8,&ep,10);
|
||||
if (!ep || (low_credit < 0))
|
||||
low_credit = 0;
|
||||
} else if (!strncmp(*argv,"ocredit=",8)) {
|
||||
oth_credit = strtol(*argv+8,&ep,10);
|
||||
if (!ep || (oth_credit < 0))
|
||||
oth_credit = 0;
|
||||
} else {
|
||||
_pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
/* this is a front-end for module-application conversations */
|
||||
static int converse(pam_handle_t *pamh, int ctrl, int nargs,
|
||||
struct pam_message **message,
|
||||
struct pam_response **response)
|
||||
{
|
||||
int retval;
|
||||
struct pam_conv *conv;
|
||||
|
||||
retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
|
||||
|
||||
if ( retval == PAM_SUCCESS ) {
|
||||
retval = conv->conv(nargs, (const struct pam_message **)message,
|
||||
response, conv->appdata_ptr);
|
||||
if (retval != PAM_SUCCESS && (ctrl && PAM_DEBUG_ARG)) {
|
||||
_pam_log(LOG_DEBUG, "conversation failure [%s]",
|
||||
pam_strerror(pamh, retval));
|
||||
}
|
||||
} else {
|
||||
_pam_log(LOG_ERR, "couldn't obtain coversation function [%s]",
|
||||
pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
return retval; /* propagate error status */
|
||||
}
|
||||
|
||||
static int make_remark(pam_handle_t *pamh, unsigned int ctrl,
|
||||
int type, const char *text)
|
||||
{
|
||||
struct pam_message *pmsg[1], msg[1];
|
||||
struct pam_response *resp;
|
||||
int retval;
|
||||
|
||||
pmsg[0] = &msg[0];
|
||||
msg[0].msg = text;
|
||||
msg[0].msg_style = type;
|
||||
resp = NULL;
|
||||
|
||||
retval = converse(pamh, ctrl, 1, pmsg, &resp);
|
||||
if (retval == PAM_SUCCESS)
|
||||
_pam_drop_reply(resp, 1);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* use this to free strings. ESPECIALLY password strings */
|
||||
static char *_pam_delete(register char *xx)
|
||||
{
|
||||
_pam_overwrite(xx);
|
||||
free(xx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* can't be a palindrome - like `R A D A R' or `M A D A M'
|
||||
*/
|
||||
static int palindrome(const char *old, const char *new)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
i = strlen (new);
|
||||
|
||||
for (j = 0;j < i;j++)
|
||||
if (new[i - j - 1] != new[j])
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* more than half of the characters are different ones.
|
||||
* or at least diff_ok are different
|
||||
* NOTE that the defaults are NOT the same as befor this
|
||||
* change. as long as there are at least 10 different bytes
|
||||
* in a new password it will now pass even if the password
|
||||
* is longer than 20 bytes (MD5)
|
||||
*/
|
||||
|
||||
static int similiar(const char *old, const char *new)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = j = 0;new[i] && old[i];i++)
|
||||
if (strchr (new, old[i]))
|
||||
j++;
|
||||
|
||||
if (j >= diff_ok || i >= j * 2)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* a nice mix of characters.
|
||||
*/
|
||||
static int simple(const char *old, const char *new)
|
||||
{
|
||||
int digits = 0;
|
||||
int uppers = 0;
|
||||
int lowers = 0;
|
||||
int others = 0;
|
||||
int size;
|
||||
int i;
|
||||
|
||||
for (i = 0;new[i];i++) {
|
||||
if (isdigit (new[i]))
|
||||
digits++;
|
||||
else if (isupper (new[i]))
|
||||
uppers++;
|
||||
else if (islower (new[i]))
|
||||
lowers++;
|
||||
else
|
||||
others++;
|
||||
}
|
||||
|
||||
/*
|
||||
* The scam was this - a password of only one character type
|
||||
* must be 8 letters long. Two types, 7, and so on.
|
||||
* This is now changed, the base size and the credits or defaults
|
||||
* see the docs on the module for info on these parameters, the
|
||||
* defaults cause the effect to be the same as before the change
|
||||
*/
|
||||
|
||||
if (digits > dig_credit)
|
||||
digits = dig_credit;
|
||||
|
||||
if (uppers > up_credit)
|
||||
uppers = up_credit;
|
||||
|
||||
if (lowers > low_credit)
|
||||
lowers = low_credit;
|
||||
|
||||
if (others > oth_credit)
|
||||
others = oth_credit;
|
||||
|
||||
size = min_length;
|
||||
size -= digits;
|
||||
size -= uppers;
|
||||
size -= lowers;
|
||||
size -= others;
|
||||
|
||||
if (size <= i)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char * str_lower(char *string)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
for (cp = string; *cp; cp++)
|
||||
*cp = tolower(*cp);
|
||||
return string;
|
||||
}
|
||||
|
||||
static const char * password_check(const char *old, const char *new)
|
||||
{
|
||||
const char *msg = NULL;
|
||||
char *oldmono, *newmono, *wrapped;
|
||||
|
||||
if (strcmp(new, old) == 0) {
|
||||
msg = "is the same as the old one";
|
||||
return msg;
|
||||
}
|
||||
|
||||
newmono = str_lower(x_strdup(new));
|
||||
oldmono = str_lower(x_strdup(old));
|
||||
wrapped = malloc(strlen(oldmono) * 2 + 1);
|
||||
strcpy (wrapped, oldmono);
|
||||
strcat (wrapped, oldmono);
|
||||
|
||||
if (palindrome(oldmono, newmono))
|
||||
msg = "is a palindrome";
|
||||
|
||||
if (!msg && strcmp(oldmono, newmono) == 0)
|
||||
msg = "case changes only";
|
||||
|
||||
if (!msg && similiar(oldmono, newmono))
|
||||
msg = "is too similiar to the old one";
|
||||
|
||||
if (!msg && simple(old, new))
|
||||
msg = "is too simple";
|
||||
|
||||
if (!msg && strstr(wrapped, newmono))
|
||||
msg = "is rotated";
|
||||
|
||||
memset(newmono, 0, strlen(newmono));
|
||||
memset(oldmono, 0, strlen(oldmono));
|
||||
memset(wrapped, 0, strlen(wrapped));
|
||||
free(newmono);
|
||||
free(oldmono);
|
||||
free(wrapped);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
static int _pam_unix_approve_pass(pam_handle_t *pamh,
|
||||
unsigned int ctrl,
|
||||
const char *pass_old,
|
||||
const char *pass_new)
|
||||
{
|
||||
const char *msg = NULL;
|
||||
|
||||
if (pass_new == NULL || (pass_old && !strcmp(pass_old,pass_new))) {
|
||||
if (ctrl && PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG, "bad authentication token");
|
||||
make_remark(pamh, ctrl, PAM_ERROR_MSG,
|
||||
pass_new == NULL ?
|
||||
"No password supplied":"Password unchanged" );
|
||||
return PAM_AUTHTOK_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* if one wanted to hardwire authentication token strength
|
||||
* checking this would be the place
|
||||
*/
|
||||
msg = password_check(pass_old,pass_new);
|
||||
if (msg) {
|
||||
char remark[BUFSIZ];
|
||||
|
||||
memset(remark,0,sizeof(remark));
|
||||
sprintf(remark,"BAD PASSWORD: %s",msg);
|
||||
if (ctrl && PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_NOTICE, "new passwd fails strength check: %s",
|
||||
msg);
|
||||
make_remark(pamh, ctrl, PAM_ERROR_MSG, remark);
|
||||
return PAM_AUTHTOK_ERR;
|
||||
};
|
||||
return PAM_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* The Main Thing (by Cristian Gafton, CEO at this module :-)
|
||||
* (stolen from http://home.netscape.com)
|
||||
*/
|
||||
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
unsigned int ctrl;
|
||||
|
||||
retry_times = 1;
|
||||
memset(prompt_type,0,sizeof(prompt_type));
|
||||
ctrl = _pam_parse(argc, argv);
|
||||
|
||||
D(("called."));
|
||||
if (!prompt_type[0])
|
||||
strcpy(prompt_type,"UNIX");
|
||||
|
||||
if (flags & PAM_PRELIM_CHECK) {
|
||||
/* Check for passwd dictionary */
|
||||
struct stat st;
|
||||
char buf[sizeof(CRACKLIB_DICTPATH)+10];
|
||||
|
||||
D(("prelim check"));
|
||||
|
||||
memset(buf,0,sizeof(buf)); /* zero the buffer */
|
||||
sprintf(buf,"%s.pwd",CRACKLIB_DICTPATH);
|
||||
|
||||
if (!stat(buf,&st) && st.st_size)
|
||||
return PAM_SUCCESS;
|
||||
else {
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_NOTICE,"dict path '%s'[.pwd] is invalid",
|
||||
CRACKLIB_DICTPATH);
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* Not reached */
|
||||
return PAM_SERVICE_ERR;
|
||||
|
||||
} else if (flags & PAM_UPDATE_AUTHTOK) {
|
||||
int retval;
|
||||
char *token1, *token2, *oldtoken;
|
||||
const char *item;
|
||||
struct pam_message msg[1],*pmsg[1];
|
||||
struct pam_response *resp;
|
||||
const char *cracklib_dictpath = CRACKLIB_DICTPATH;
|
||||
char prompt[BUFSIZ];
|
||||
|
||||
D(("do update"));
|
||||
retval = pam_get_item(pamh, PAM_OLDAUTHTOK,
|
||||
(const void **)&oldtoken);
|
||||
if (retval != PAM_SUCCESS) {
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_ERR,"Can not get old passwd");
|
||||
oldtoken=NULL;
|
||||
retval = PAM_SUCCESS;
|
||||
}
|
||||
|
||||
do {
|
||||
/*
|
||||
* make sure nothing inappropriate gets returned
|
||||
*/
|
||||
token1 = token2 = NULL;
|
||||
|
||||
if (!retry_times) {
|
||||
D(("returning %s because maxtries reached",
|
||||
pam_strerror(pamh, retval)));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Planned modus operandi:
|
||||
* Get a passwd.
|
||||
* Verify it against cracklib.
|
||||
* If okay get it a second time.
|
||||
* Check to be the same with the first one.
|
||||
* set PAM_AUTHTOK and return
|
||||
*/
|
||||
|
||||
/* Prepare to ask the user for the first time */
|
||||
memset(prompt,0,sizeof(prompt));
|
||||
sprintf(prompt,PROMPT1,prompt_type);
|
||||
pmsg[0] = &msg[0];
|
||||
msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
|
||||
msg[0].msg = prompt;
|
||||
|
||||
resp = NULL;
|
||||
retval = converse(pamh, ctrl, 1, pmsg, &resp);
|
||||
if (resp != NULL) {
|
||||
/* interpret the response */
|
||||
if (retval == PAM_SUCCESS) { /* a good conversation */
|
||||
token1 = x_strdup(resp[0].resp);
|
||||
if (token1 == NULL) {
|
||||
_pam_log(LOG_NOTICE,
|
||||
"could not recover authentication token 1");
|
||||
retval = PAM_AUTHTOK_RECOVER_ERR;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* tidy up the conversation (resp_retcode) is ignored
|
||||
*/
|
||||
_pam_drop_reply(resp, 1);
|
||||
} else {
|
||||
retval = (retval == PAM_SUCCESS) ?
|
||||
PAM_AUTHTOK_RECOVER_ERR:retval ;
|
||||
}
|
||||
|
||||
if (retval != PAM_SUCCESS) {
|
||||
if (ctrl && PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG,"unable to obtain a password");
|
||||
continue;
|
||||
}
|
||||
|
||||
D(("testing password, retval = %s", pam_strerror(pamh, retval)));
|
||||
/* now test this passwd against cracklib */
|
||||
{
|
||||
char *crack_msg;
|
||||
char remark[BUFSIZ];
|
||||
|
||||
bzero(remark,sizeof(remark));
|
||||
D(("against cracklib"));
|
||||
if ((crack_msg = FascistCheck(token1, cracklib_dictpath))) {
|
||||
if (ctrl && PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG,"bad password: %s",crack_msg);
|
||||
sprintf(remark,"BAD PASSWORD: %s", crack_msg);
|
||||
make_remark(pamh, ctrl, PAM_ERROR_MSG, remark);
|
||||
if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK))
|
||||
retval = PAM_AUTHTOK_ERR;
|
||||
else
|
||||
retval = PAM_SUCCESS;
|
||||
} else {
|
||||
/* check it for strength too... */
|
||||
D(("for strength"));
|
||||
if (oldtoken) {
|
||||
retval = _pam_unix_approve_pass(pamh,ctrl,
|
||||
oldtoken,token1);
|
||||
if (retval != PAM_SUCCESS)
|
||||
if (getuid() || (flags & PAM_CHANGE_EXPIRED_AUTHTOK))
|
||||
retval = PAM_AUTHTOK_ERR;
|
||||
else
|
||||
retval = PAM_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D(("after testing: retval = %s", pam_strerror(pamh, retval)));
|
||||
/* if cracklib/strength check said it is a bad passwd... */
|
||||
if ((retval != PAM_SUCCESS) && (retval != PAM_IGNORE)) {
|
||||
int temp_unused;
|
||||
|
||||
temp_unused = pam_set_item(pamh, PAM_AUTHTOK, NULL);
|
||||
token1 = _pam_delete(token1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Now we have a good passwd. Ask for it once again */
|
||||
|
||||
bzero(prompt,sizeof(prompt));
|
||||
sprintf(prompt,PROMPT2,prompt_type);
|
||||
pmsg[0] = &msg[0];
|
||||
msg[0].msg_style = PAM_PROMPT_ECHO_OFF;
|
||||
msg[0].msg = prompt;
|
||||
|
||||
resp = NULL;
|
||||
retval = converse(pamh, ctrl, 1, pmsg, &resp);
|
||||
if (resp != NULL) {
|
||||
/* interpret the response */
|
||||
if (retval == PAM_SUCCESS) { /* a good conversation */
|
||||
token2 = x_strdup(resp[0].resp);
|
||||
if (token2 == NULL) {
|
||||
_pam_log(LOG_NOTICE,
|
||||
"could not recover authentication token 2");
|
||||
retval = PAM_AUTHTOK_RECOVER_ERR;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* tidy up the conversation (resp_retcode) is ignored
|
||||
*/
|
||||
_pam_drop_reply(resp, 1);
|
||||
} else {
|
||||
retval = (retval == PAM_SUCCESS) ?
|
||||
PAM_AUTHTOK_RECOVER_ERR:retval ;
|
||||
}
|
||||
|
||||
if (retval != PAM_SUCCESS) {
|
||||
if (ctrl && PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG
|
||||
,"unable to obtain the password a second time");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Hopefully now token1 and token2 the same password ... */
|
||||
if (strcmp(token1,token2) != 0) {
|
||||
/* tell the user */
|
||||
make_remark(pamh, ctrl, PAM_ERROR_MSG, MISTYPED_PASS);
|
||||
token1 = _pam_delete(token1);
|
||||
token2 = _pam_delete(token2);
|
||||
pam_set_item(pamh, PAM_AUTHTOK, NULL);
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_NOTICE,"Password mistyped");
|
||||
retval = PAM_AUTHTOK_RECOVER_ERR;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Yes, the password was typed correct twice
|
||||
* we store this password as an item
|
||||
*/
|
||||
|
||||
retval = pam_set_item(pamh, PAM_AUTHTOK, token1);
|
||||
/* clean it up */
|
||||
token1 = _pam_delete(token1);
|
||||
token2 = _pam_delete(token2);
|
||||
if (
|
||||
(retval != PAM_SUCCESS) ||
|
||||
(
|
||||
(
|
||||
retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&item)
|
||||
) != PAM_SUCCESS
|
||||
)
|
||||
) {
|
||||
_pam_log(LOG_CRIT, "error manipulating password");
|
||||
continue;
|
||||
}
|
||||
item = NULL; /* break link to password */
|
||||
return PAM_SUCCESS;
|
||||
|
||||
} while (retry_times--);
|
||||
|
||||
} else {
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_NOTICE, "UNKNOWN flags setting %02X",flags);
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
/* Not reached */
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
/* static module data */
|
||||
struct pam_module _pam_cracklib_modstruct = {
|
||||
"pam_cracklib",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
pam_sm_chauthtok
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) Cristian Gafton <gafton@redhat.com>, 1996.
|
||||
* All rights reserved
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* The following copyright was appended for the long password support
|
||||
* added with the libpam 0.58 release:
|
||||
*
|
||||
* Modificaton Copyright (c) Philip W. Dalrymple III <pwd@mdtsoft.com>
|
||||
* 1997. All rights reserved
|
||||
*
|
||||
* THE MODIFICATION THAT PROVIDES SUPPORT FOR LONG PASSWORD TYPE CHECKING TO
|
||||
* 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.
|
||||
*/
|
@ -1,125 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.7 1997/04/05 06:43:41 morgan Exp morgan $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.7 1997/04/05 06:43:41 morgan
|
||||
# full-source-tree and fakeroot
|
||||
#
|
||||
# Revision 1.6 1997/02/15 19:04:27 morgan
|
||||
# fixed email
|
||||
#
|
||||
# Revision 1.5 1996/11/10 20:11:48 morgan
|
||||
# crossplatform support
|
||||
#
|
||||
# Revision 1.4 1996/09/05 06:50:12 morgan
|
||||
# ld --> gcc
|
||||
#
|
||||
# Revision 1.3 1996/05/26 15:48:38 morgan
|
||||
# make dynamic and static dirs
|
||||
#
|
||||
# Revision 1.2 1996/05/26 04:00:16 morgan
|
||||
# changes for automated static/dynamic modules
|
||||
#
|
||||
# Revision 1.1 1996/03/16 17:47:36 morgan
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11
|
||||
#
|
||||
|
||||
# Convenient defaults for compiling independently of the full source
|
||||
# tree.
|
||||
ifndef FULL_LINUX_PAM_SOURCE_TREE
|
||||
export DYNAMIC=-DPAM_DYNAMIC
|
||||
export CC=gcc
|
||||
export CFLAGS=-O2 -Dlinux -DLINUX_PAM \
|
||||
-ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \
|
||||
-Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \
|
||||
-Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \
|
||||
-Wshadow -pedantic -fPIC
|
||||
export MKDIR=mkdir -p
|
||||
export LD_D=gcc -shared -Xlinker -x
|
||||
endif
|
||||
|
||||
#
|
||||
|
||||
TITLE=pam_deny
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,4 +0,0 @@
|
||||
# $Id: README,v 1.1 1996/03/16 18:11:12 morgan Exp $
|
||||
#
|
||||
|
||||
this module always fails, it ignores all options.
|
@ -1,94 +0,0 @@
|
||||
/* pam_permit module */
|
||||
|
||||
/*
|
||||
* $Id: pam_deny.c,v 1.4 1997/02/15 19:05:15 morgan Exp $
|
||||
*
|
||||
* Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11
|
||||
*
|
||||
* $Log: pam_deny.c,v $
|
||||
* Revision 1.4 1997/02/15 19:05:15 morgan
|
||||
* fixed email
|
||||
*
|
||||
* Revision 1.3 1996/06/02 08:06:19 morgan
|
||||
* changes for new static protocol
|
||||
*
|
||||
* Revision 1.2 1996/05/26 04:01:12 morgan
|
||||
* added static support
|
||||
*
|
||||
* Revision 1.1 1996/03/16 17:47:36 morgan
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* here, we make definitions for the externally accessible functions
|
||||
* in this file (these definitions are required for static modules
|
||||
* but strongly encouraged generally) they are used to instruct the
|
||||
* modules include file to define their prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
#define PAM_SM_ACCOUNT
|
||||
#define PAM_SM_SESSION
|
||||
#define PAM_SM_PASSWORD
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
|
||||
/* --- authentication management functions --- */
|
||||
|
||||
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_CRED_UNAVAIL;
|
||||
}
|
||||
|
||||
/* --- account management functions --- */
|
||||
|
||||
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_ACCT_EXPIRED;
|
||||
}
|
||||
|
||||
/* --- password management --- */
|
||||
|
||||
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_AUTHTOK_ERR;
|
||||
}
|
||||
|
||||
/* --- session management --- */
|
||||
|
||||
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_SYSTEM_ERR;
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_SYSTEM_ERR;
|
||||
}
|
||||
|
||||
/* end of module definition */
|
||||
|
||||
/* static module data */
|
||||
#ifdef PAM_STATIC
|
||||
struct pam_module _pam_deny_modstruct = {
|
||||
"pam_deny",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
pam_sm_acct_mgmt,
|
||||
pam_sm_open_session,
|
||||
pam_sm_close_session,
|
||||
pam_sm_chauthtok
|
||||
};
|
||||
#endif
|
@ -1,107 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.1 1997/04/05 06:42:35 morgan Exp morgan $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.1 1997/04/05 06:42:35 morgan
|
||||
# Initial revision
|
||||
#
|
||||
# Revision 1.1 1997/01/04 20:32:52 morgan
|
||||
# Initial revision
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/12/8
|
||||
# Adaptations by Dave Kinclea and Cristian Gafton
|
||||
#
|
||||
|
||||
TITLE=pam_env
|
||||
|
||||
CONFD=$(CONFIGED)/security
|
||||
export CONFD
|
||||
CONFILE=$(CONFD)/pam_env.conf
|
||||
export CONFILE
|
||||
|
||||
#ifeq ($(HAVE_PWDBLIB),yes)
|
||||
#CFLAGS += -DWANT_PWDB
|
||||
#EXTRALIB = -lpwdb
|
||||
#endif
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD) $(EXTRALIB)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS) $(EXTRALIB)
|
||||
endif
|
||||
|
||||
install: all
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
$(MKDIR) $(FAKEROOT)$(SCONFIGED)
|
||||
bash -f ./install_conf
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak dynamic/* static/*
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,72 +0,0 @@
|
||||
# $Date: 1997/04/05 06:42:35 $
|
||||
# $Author: morgan $
|
||||
# $Id: README,v 1.1 1997/04/05 06:42:35 morgan Exp $
|
||||
#
|
||||
# This is the configuration file for pam_env, a PAM module to load in
|
||||
# a configurable list of environment variables for a
|
||||
#
|
||||
# The original idea for this came from Andrew G. Morgan ...
|
||||
#<quote>
|
||||
# Mmm. Perhaps you might like to write a pam_env module that reads a
|
||||
# default environment from a file? I can see that as REALLY
|
||||
# useful... Note it would be an "auth" module that returns PAM_IGNORE
|
||||
# for the auth part and sets the environment returning PAM_SUCCESS in
|
||||
# the setcred function...
|
||||
#</quote>
|
||||
#
|
||||
# What I wanted was the REMOTEHOST variable set, purely for selfish
|
||||
# reasons, and AGM didn't want it added to the SimpleApps login
|
||||
# program (which is where I added the patch). So, my first concern is
|
||||
# that variable, from there there are numerous others that might/would
|
||||
# be useful to be set: NNTPSERVER, LESS, PATH, PAGER, MANPAGER .....
|
||||
#
|
||||
# Of course, these are a different kind of variable than REMOTEHOST in
|
||||
# that they are things that are likely to be configured by
|
||||
# administrators rather than set by logging in, how to treat them both
|
||||
# in the same config file?
|
||||
#
|
||||
# Here is my idea:
|
||||
#
|
||||
# Each line starts with the variable name, there are then two possible
|
||||
# options for each variable DEFAULT and OVERRIDE.
|
||||
# DEFAULT allows and administrator to set the value of the
|
||||
# variable to some default value, if none is supplied then the empty
|
||||
# string is assumed. The OVERRIDE option tells pam_env that it should
|
||||
# enter in its value (overriding the default value) if there is one
|
||||
# to use. OVERRIDE is not used, "" is assumed and no override will be
|
||||
# done.
|
||||
#
|
||||
# VARIABLE [DEFAULT=[value]] [OVERRIDE=[value]]
|
||||
#
|
||||
# (Possibly non-existent) environment variables may be used in values
|
||||
# using the ${string} syntax and (possibly non-existent) PAM_ITEMs may
|
||||
# be used in values using the @{string} syntax. Both the $ and @
|
||||
# characters can be backslash escaped to be used as literal values
|
||||
# values can be delimited with "", escaped " not supported.
|
||||
#
|
||||
#
|
||||
# First, some special variables
|
||||
#
|
||||
# Set the REMOTEHOST variable for any hosts that are remote, default
|
||||
# to "localhost" rather than not being set at all
|
||||
REMOTEHOST DEFAULT=localhost OVERRIDE=@{PAM_RHOST}
|
||||
#
|
||||
# Set the DISPLAY variable if it seems reasonable
|
||||
DISPLAY DEFAULT=${REMOTEHOST}:0.0 OVERRIDE=${DISPLAY}
|
||||
#
|
||||
#
|
||||
# Now some simple variables
|
||||
#
|
||||
PAGER DEFAULT=less
|
||||
MANPAGER DEFAULT=less
|
||||
LESS DEFAULT="M q e h15 z23 b80"
|
||||
NNTPSERVER DEFAULT=localhost
|
||||
PATH DEFAULT=${HOME}/bin:/usr/local/bin:/bin\
|
||||
:/usr/bin:/usr/local/bin/X11:/usr/bin/X11
|
||||
#
|
||||
# silly examples of escaped variables, just to show how they work.
|
||||
#
|
||||
DOLLAR DEFAULT=\$
|
||||
DOLLARDOLLAR DEFAULT= OVERRIDE=\$${DOLLAR}
|
||||
DOLLARPLUS DEFAULT=\${REMOTEHOST}${REMOTEHOST}
|
||||
ATSIGN DEFAULT="" OVERRIDE=\@
|
@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFILE=$FAKEROOT"$CONFILE"
|
||||
IGNORE_AGE=./.ignore_age
|
||||
QUIET_INSTALL=../../.quiet_install
|
||||
CONF=./pam_env.conf-example
|
||||
MODULE=pam_env
|
||||
|
||||
echo
|
||||
|
||||
if [ -f "$QUIET_INSTALL" ]; then
|
||||
if [ ! -f "$CONFILE" ]; then
|
||||
yes="y"
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
elif [ -f "$IGNORE_AGE" ]; then
|
||||
echo "you don't want to be bothered with the age of your $CONFILE file"
|
||||
yes="n"
|
||||
elif [ ! -f "$CONFILE" ] || [ "$CONF" -nt "$CONFILE" ]; then
|
||||
if [ -f "$CONFILE" ]; then
|
||||
echo "An older $MODULE configuration file already exists ($CONFILE)"
|
||||
echo "Do you wish to copy the $CONF file in this distribution"
|
||||
echo "to $CONFILE ? (y/n) [skip] "
|
||||
read yes
|
||||
else
|
||||
yes="y"
|
||||
fi
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
|
||||
if [ "$yes" = "y" ]; then
|
||||
mkdir -p $FAKEROOT$CONFD
|
||||
echo " copying $CONF to $CONFILE"
|
||||
cp $CONF $CONFILE
|
||||
else
|
||||
echo " Skipping $CONF installation"
|
||||
if [ "$yes" = "n" ]; then
|
||||
touch "$IGNORE_AGE"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
@ -1,779 +0,0 @@
|
||||
/* pam_mail module */
|
||||
|
||||
/*
|
||||
* $Id: pam_env.c,v 1.1 1997/04/05 06:42:35 morgan Exp morgan $
|
||||
*
|
||||
* Written by Dave Kinchlea <kinch@kinch.ark.com> 1997/01/31
|
||||
* Inspired by Andrew Morgan <morgan@parc.power.net, who also supplied the
|
||||
* template for this file (via pam_mail)
|
||||
*
|
||||
* $Log: pam_env.c,v $
|
||||
* Revision 1.1 1997/04/05 06:42:35 morgan
|
||||
* Initial revision
|
||||
*
|
||||
* Revision 0.6 1997/02/04 17:58:27 kinch
|
||||
* Debugging code cleaned up, lots added (whereever _log_err called) some removed
|
||||
*
|
||||
* Revision 0.5 1997/02/04 17:20:30 kinch
|
||||
* Changed default config file
|
||||
* Removed bogus message in pam_sm_authenticate()
|
||||
* Added back support in pam_sm_session(), this could conceivably be used
|
||||
* both as an auth_setcred and a session module
|
||||
*
|
||||
* Revision 0.4 1997/02/04 07:34:15 kinch
|
||||
* Fixed dealing with escaped '$' and '@' characters
|
||||
* This is now an pam_sm_setcred module to work closer to the RFC model
|
||||
* though this whole thing seems to have little to do with Authentication
|
||||
*
|
||||
* Revision 0.3 1997/02/04 04:53:15 kinch
|
||||
* Removed bogus space in PAM_ENV_SILENT
|
||||
* Removed line that added a space when allowing for escaped newlines, that
|
||||
* is not what we want at all, if we want a space, we can add one.
|
||||
* Changed a PAM_ABORT to PAM_BUF_ERR for a malloc failure
|
||||
* Changed bogus PAM_RUSER to PAM_RHOST
|
||||
*
|
||||
* Revision 0.2 1997/02/03 23:31:26 kinch
|
||||
* Lots of D(()) debugging code added, probably too much actually.
|
||||
* This now seems to work for all cases I can think of
|
||||
* Lots of little code changes but nothing major and no function
|
||||
* interface changes, largest change has to do with adding the
|
||||
* logic to get "e hack to make it through all the code. Probably
|
||||
* ought to have done this with a global flag for each of defval and
|
||||
* override - it would have been cleaner.
|
||||
*
|
||||
* Revision 0.1 1997/02/03 01:39:06 kinch
|
||||
* Initial code, it compiles cleanly but has not been tested at all.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef DEFAULT_CONF_FILE
|
||||
#define DEFAULT_CONF_FILE "/etc/security/pam_env.conf"
|
||||
#endif
|
||||
|
||||
#ifdef linux
|
||||
#define _GNU_SOURCE
|
||||
#include <features.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef WANT_PWDB
|
||||
#include <pwdb/pwdb_public.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* here, we make a definition for the externally accessible function
|
||||
* in this file (this definition is required for static a module
|
||||
* but strongly encouraged generally) it is used to instruct the
|
||||
* modules include file to define the function prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_AUTH /* This is primarily a AUTH_SETCRED module */
|
||||
#define PAM_SM_SESSION /* But I like to be friendly */
|
||||
#define PAM_SM_PASSWORD /* "" */
|
||||
#define PAM_SM_ACCOUNT /* "" */
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
/* This little structure makes it easier to keep variables together */
|
||||
|
||||
typedef struct var {
|
||||
char *name;
|
||||
char *value;
|
||||
char *defval;
|
||||
char *override;
|
||||
} VAR;
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
#define MAX_ENV 8192
|
||||
|
||||
#define GOOD_LINE 0
|
||||
#define BAD_LINE 100 /* This must be > the largest PAM_* error code */
|
||||
|
||||
#define DEFINE_VAR 101
|
||||
#define UNDEFINE_VAR 102
|
||||
#define ILLEGAL_VAR 103
|
||||
|
||||
static int _assemble_line(FILE *, char *, int);
|
||||
static int _parse_line(char *, VAR *);
|
||||
static int _check_var(pam_handle_t *, VAR *); /* This is the real meat */
|
||||
static void _clean_var(VAR *);
|
||||
static int _expand_arg(pam_handle_t *, char **);
|
||||
static const char * _pam_get_item_byname(pam_handle_t *, const char *);
|
||||
static int _define_var(pam_handle_t *, VAR *);
|
||||
static int _undefine_var(pam_handle_t *, VAR *);
|
||||
|
||||
/* This is a flag used to designate an empty string */
|
||||
static char quote='Z';
|
||||
|
||||
/* some syslogging */
|
||||
|
||||
static void _log_err(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("PAM-env", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
/* argument parsing */
|
||||
|
||||
#define PAM_DEBUG_ARG 01
|
||||
#define PAM_NEW_CONF_FILE 02
|
||||
#define PAM_ENV_SILENT 04
|
||||
|
||||
static int _pam_parse(int flags, int argc, const char **argv, char **conffile)
|
||||
{
|
||||
int ctrl=0;
|
||||
|
||||
|
||||
/* step through arguments */
|
||||
for (; argc-- > 0; ++argv) {
|
||||
|
||||
/* generic options */
|
||||
|
||||
if (!strcmp(*argv,"debug"))
|
||||
ctrl |= PAM_DEBUG_ARG;
|
||||
else if (!strncmp(*argv,"conffile=",9)) {
|
||||
*conffile = x_strdup(9+*argv);
|
||||
if (*conffile != NULL) {
|
||||
D(("new Configuration File: %s", *conffile));
|
||||
ctrl |= PAM_NEW_CONF_FILE;
|
||||
} else {
|
||||
_log_err(LOG_CRIT,
|
||||
"Configuration file specification missing argument - ignored");
|
||||
}
|
||||
} else {
|
||||
_log_err(LOG_ERR,"pam_parse: unknown option; %s",*argv);
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
static int _parse_config_file(pam_handle_t *pamh, int ctrl, char **conffile)
|
||||
{
|
||||
int retval;
|
||||
const char *file;
|
||||
char buffer[BUF_SIZE];
|
||||
FILE *conf;
|
||||
VAR Var, *var=&Var;
|
||||
|
||||
var->name=NULL; var->defval=NULL; var->override=NULL;
|
||||
D(("Called."));
|
||||
|
||||
if (ctrl & PAM_NEW_CONF_FILE) {
|
||||
file = *conffile;
|
||||
} else {
|
||||
file = DEFAULT_CONF_FILE;
|
||||
}
|
||||
|
||||
D(("Config file name is: %s", file));
|
||||
|
||||
/*
|
||||
* Lets try to open the config file, parse it and process
|
||||
* any variables found.
|
||||
*/
|
||||
|
||||
if ((conf = fopen(file,"r")) == NULL) {
|
||||
_log_err(LOG_ERR, "Unable to open config file: %s",
|
||||
strerror(errno));
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* _pam_assemble_line will provide a complete line from the config file, with all
|
||||
* comments removed and any escaped newlines fixed up
|
||||
*/
|
||||
|
||||
while (( retval = _assemble_line(conf, buffer, BUF_SIZE)) > 0) {
|
||||
D(("Read line: %s", buffer));
|
||||
|
||||
if ((retval = _parse_line(buffer, var)) == GOOD_LINE) {
|
||||
retval = _check_var(pamh, var);
|
||||
|
||||
if (DEFINE_VAR == retval) {
|
||||
retval = _define_var(pamh, var);
|
||||
|
||||
} else if (UNDEFINE_VAR == retval) {
|
||||
retval = _undefine_var(pamh, var);
|
||||
}
|
||||
}
|
||||
if (PAM_SUCCESS != retval && ILLEGAL_VAR != retval
|
||||
&& BAD_LINE != retval && PAM_BAD_ITEM != retval) break;
|
||||
|
||||
_clean_var(var);
|
||||
|
||||
} /* while */
|
||||
|
||||
(void) fclose(conf);
|
||||
|
||||
/* tidy up */
|
||||
_clean_var(var); /* We could have got here prematurely, this is safe though */
|
||||
_pam_overwrite(*conffile);
|
||||
_pam_drop(*conffile);
|
||||
file = NULL;
|
||||
D(("Exit."));
|
||||
return (retval<0?PAM_ABORT:PAM_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is where we read a line of the PAM config file. The line may be
|
||||
* preceeded by lines of comments and also extended with "\\\n"
|
||||
*/
|
||||
|
||||
static int _assemble_line(FILE *f, char *buffer, int buf_len)
|
||||
{
|
||||
char *p = buffer;
|
||||
char *s, *os;
|
||||
int used = 0;
|
||||
|
||||
/* loop broken with a 'break' when a non-'\\n' ended line is read */
|
||||
|
||||
D(("called."));
|
||||
for (;;) {
|
||||
if (used >= buf_len) {
|
||||
/* Overflow */
|
||||
D(("_assemble_line: overflow"));
|
||||
return -1;
|
||||
}
|
||||
if (fgets(p, buf_len - used, f) == NULL) {
|
||||
if (used) {
|
||||
/* Incomplete read */
|
||||
return -1;
|
||||
} else {
|
||||
/* EOF */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip leading spaces --- line may be blank */
|
||||
|
||||
s = p + strspn(p, " \n\t");
|
||||
if (*s && (*s != '#')) {
|
||||
os = s;
|
||||
|
||||
/*
|
||||
* we are only interested in characters before the first '#'
|
||||
* character
|
||||
*/
|
||||
|
||||
while (*s && *s != '#')
|
||||
++s;
|
||||
if (*s == '#') {
|
||||
*s = '\0';
|
||||
used += strlen(os);
|
||||
break; /* the line has been read */
|
||||
}
|
||||
|
||||
s = os;
|
||||
|
||||
/*
|
||||
* Check for backslash by scanning back from the end of
|
||||
* the entered line, the '\n' has been included since
|
||||
* normally a line is terminated with this
|
||||
* character. fgets() should only return one though!
|
||||
*/
|
||||
|
||||
s += strlen(s);
|
||||
while (s > os && ((*--s == ' ') || (*s == '\t')
|
||||
|| (*s == '\n')));
|
||||
|
||||
/* check if it ends with a backslash */
|
||||
if (*s == '\\') {
|
||||
*s = '\0'; /* truncate the line here */
|
||||
used += strlen(os);
|
||||
p = s; /* there is more ... */
|
||||
} else {
|
||||
/* End of the line! */
|
||||
used += strlen(os);
|
||||
break; /* this is the complete line */
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Nothing in this line */
|
||||
/* Don't move p */
|
||||
}
|
||||
}
|
||||
|
||||
return used;
|
||||
}
|
||||
|
||||
static int _parse_line(char *buffer, VAR *var)
|
||||
{
|
||||
/*
|
||||
* parse buffer into var, legal syntax is
|
||||
* VARIABLE [DEFAULT=[[string]] [OVERRIDE=[value]]
|
||||
*
|
||||
* Any other options defined make this a bad line,
|
||||
* error logged and no var set
|
||||
*/
|
||||
|
||||
int length, quoteflg=0;
|
||||
char *ptr, **valptr, *tmpptr;
|
||||
|
||||
D(("Called buffer = <%s>", buffer));
|
||||
|
||||
length = strcspn(buffer," \t\n");
|
||||
|
||||
if ((var->name = malloc(length + 1)) == NULL) {
|
||||
_log_err(LOG_ERR, "Couldn't malloc %d bytes", length+1);
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
|
||||
/*
|
||||
* The first thing on the line HAS to be the variable name,
|
||||
* it may be the only thing though.
|
||||
*/
|
||||
strncpy(var->name, buffer, length);
|
||||
var->name[length] = '\0';
|
||||
D(("var->name = <%s>, length = %d", var->name, length));
|
||||
|
||||
/*
|
||||
* Now we check for arguments, we only support two kinds and ('cause I am lazy)
|
||||
* each one can actually be listed any number of times
|
||||
*/
|
||||
|
||||
ptr = buffer+length;
|
||||
while ((length = strspn(ptr, " \t")) > 0) {
|
||||
ptr += length; /* remove leading whitespace */
|
||||
D((ptr));
|
||||
if (strncmp(ptr,"DEFAULT=",8) == 0) {
|
||||
ptr+=8;
|
||||
D(("Default arg found: <%s>", ptr));
|
||||
valptr=&(var->defval);
|
||||
} else if (strncmp(ptr, "OVERRIDE=", 9) == 0) {
|
||||
ptr+=9;
|
||||
D(("Override arg found: <%s>", ptr));
|
||||
valptr=&(var->override);
|
||||
} else {
|
||||
D(("Unrecognized options: <%s> - ignoring line", ptr));
|
||||
_log_err(LOG_ERR, "Unrecognized Option: %s - ignoring line", ptr);
|
||||
return BAD_LINE;
|
||||
}
|
||||
|
||||
if ('"' != *ptr) { /* Escaped quotes not supported */
|
||||
length = strcspn(ptr, " \t\n");
|
||||
tmpptr = ptr+length;
|
||||
} else {
|
||||
tmpptr = strchr(++ptr, '"');
|
||||
if (!tmpptr) {
|
||||
D(("Unterminated quoted string: %s", ptr-1));
|
||||
_log_err(LOG_ERR, "Unterminated quoted string: %s", ptr-1);
|
||||
return BAD_LINE;
|
||||
}
|
||||
length = tmpptr - ptr;
|
||||
if (*++tmpptr && ' ' != *tmpptr && '\t' != *tmpptr && '\n' != *tmpptr) {
|
||||
D(("Quotes must cover the entire string: <%s>", ptr));
|
||||
_log_err(LOG_ERR, "Quotes must cover the entire string: <%s>", ptr);
|
||||
return BAD_LINE;
|
||||
}
|
||||
quoteflg++;
|
||||
}
|
||||
if (length) {
|
||||
if ((*valptr = malloc(length + 1)) == NULL) {
|
||||
D(("Couldn't malloc %d bytes", length+1));
|
||||
_log_err(LOG_ERR, "Couldn't malloc %d bytes", length+1);
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
(void)strncpy(*valptr,ptr,length);
|
||||
(*valptr)[length]='\0';
|
||||
} else if (quoteflg--) {
|
||||
*valptr = "e; /* a quick hack to handle the empty string */
|
||||
}
|
||||
ptr = tmpptr; /* Start the search where we stopped */
|
||||
} /* while */
|
||||
|
||||
/*
|
||||
* The line is parsed, all is well.
|
||||
*/
|
||||
|
||||
D(("Exit."));
|
||||
ptr = NULL; tmpptr = NULL; valptr = NULL;
|
||||
return GOOD_LINE;
|
||||
}
|
||||
|
||||
static int _check_var(pam_handle_t *pamh, VAR *var)
|
||||
{
|
||||
/*
|
||||
* Examine the variable and determine what action to take.
|
||||
* Returns DEFINE_VAR, UNDEFINE_VAR depending on action to take
|
||||
* or a PAM_* error code if passed back from other routines
|
||||
*
|
||||
* if no DEFAULT provided, the empty string is assumed
|
||||
* if no OVERRIDE provided, the empty string is assumed
|
||||
* if DEFAULT= and OVERRIDE evaluates to the empty string,
|
||||
* this variable should be undefined
|
||||
* if DEFAULT="" and OVERRIDE evaluates to the empty string,
|
||||
* this variable should be defined with no value
|
||||
* if OVERRIDE=value and value turns into the empty string, DEFAULT is used
|
||||
*
|
||||
* If DEFINE_VAR is to be returned, the correct value to define will
|
||||
* be pointed to by var->value
|
||||
*/
|
||||
|
||||
int retval;
|
||||
|
||||
D(("Called."));
|
||||
|
||||
/*
|
||||
* First thing to do is to expand any arguments, but only
|
||||
* if they are not the special quote values (cause expand_arg
|
||||
* changes memory).
|
||||
*/
|
||||
|
||||
if (var->defval && ("e != var->defval) &&
|
||||
((retval = _expand_arg(pamh, &(var->defval))) != PAM_SUCCESS)) {
|
||||
return retval;
|
||||
}
|
||||
if (var->override && ("e != var->override) &&
|
||||
((retval = _expand_arg(pamh, &(var->override))) != PAM_SUCCESS)) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Now its easy */
|
||||
|
||||
if (var->override && *(var->override) && "e != var->override) {
|
||||
/* if there is a non-empty string in var->override, we use it */
|
||||
D(("OVERRIDE variable <%s> being used: <%s>", var->name, var->override));
|
||||
var->value = var->override;
|
||||
retval = DEFINE_VAR;
|
||||
} else {
|
||||
|
||||
var->value = var->defval;
|
||||
if ("e == var->defval) {
|
||||
/*
|
||||
* This means that the empty string was given for defval value
|
||||
* which indicates that a variable should be defined with no value
|
||||
*/
|
||||
*var->defval = '\0';
|
||||
D(("An empty variable: <%s>", var->name));
|
||||
retval = DEFINE_VAR;
|
||||
} else if (var->defval) {
|
||||
D(("DEFAULT variable <%s> being used: <%s>", var->name, var->defval));
|
||||
retval = DEFINE_VAR;
|
||||
} else {
|
||||
D(("UNDEFINE variable <%s>", var->name));
|
||||
retval = UNDEFINE_VAR;
|
||||
}
|
||||
}
|
||||
|
||||
D(("Exit."));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int _expand_arg(pam_handle_t *pamh, char **value)
|
||||
{
|
||||
const char *orig=*value, *tmpptr=NULL;
|
||||
char *ptr; /*
|
||||
* Sure would be nice to use tmpptr but it needs to be
|
||||
* a constant so that the compiler will shut up when I
|
||||
* call pam_getenv and _pam_get_item_byname -- sigh
|
||||
*/
|
||||
|
||||
char type, tmpval[BUF_SIZE]; /* No unexpanded variable can be bigger than BUF_SIZE */
|
||||
char tmp[MAX_ENV]; /* I know this shouldn't be hard-coded but it's so
|
||||
* much easier this way */
|
||||
|
||||
D(("Remember to initialize tmp!"));
|
||||
tmp[0] = '\0';
|
||||
|
||||
/*
|
||||
* (possibly non-existent) environment variables can be used as values
|
||||
* by prepending a "$" and wrapping in {} (ie: ${HOST}), can escape with "\"
|
||||
* (possibly non-existent) PAM items can be used as values
|
||||
* by prepending a "@" and wrapping in {} (ie: @{PAM_RHOST}, can escape
|
||||
*
|
||||
*/
|
||||
D(("Expanding <%s>",orig));
|
||||
while (*orig) { /* while there is some input to deal with */
|
||||
if ('\\' == *orig) {
|
||||
++orig;
|
||||
if ('$' != *orig && '@' != *orig) {
|
||||
D(("Unrecognized escaped character: <%c> - ignoring", *orig));
|
||||
_log_err(LOG_ERR, "Unrecognized escaped character: <%c> - ignoring",
|
||||
*orig);
|
||||
} else if ((strlen(tmp) + 1) < MAX_ENV) {
|
||||
tmp[strlen(tmp)] = *orig++; /* Note the increment */
|
||||
} else {
|
||||
/* is it really a good idea to try to log this? */
|
||||
D(("Variable buffer overflow: <%s> + <%s>", tmp, tmpptr));
|
||||
_log_err(LOG_ERR, "Variable buffer overflow: <%s> + <%s>", tmp, tmpptr);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ('$' == *orig || '@' == *orig) {
|
||||
if ('{' != *(orig+1)) {
|
||||
D(("Expandable variables must be wrapped in {} <%s> - ignoring", orig));
|
||||
_log_err(LOG_ERR, "Expandable variables must be wrapped in {} <%s> - ignoring",
|
||||
orig);
|
||||
if ((strlen(tmp) + 1) < MAX_ENV) {
|
||||
tmp[strlen(tmp)] = *orig++; /* Note the increment */
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
D(("Expandable argument: <%s>", orig));
|
||||
type = *orig;
|
||||
orig+=2; /* skip the ${ or @{ characters */
|
||||
ptr = strchr(orig, '}');
|
||||
if (ptr) {
|
||||
*ptr++ = '\0';
|
||||
} else {
|
||||
D(("Unterminated expandable variable: <%s>", orig-2));
|
||||
_log_err(LOG_ERR, "Unterminated expandable variable: <%s>", orig-2);
|
||||
return PAM_ABORT;
|
||||
}
|
||||
strcpy(tmpval, orig);
|
||||
orig=ptr;
|
||||
/*
|
||||
* so, we know we need to expand tmpval, it is either
|
||||
* an environment variable or a PAM_ITEM. type will tell us which
|
||||
*/
|
||||
switch (type) {
|
||||
|
||||
case '$':
|
||||
D(("Expanding env var: <%s>",tmpval));
|
||||
tmpptr = pam_getenv(pamh, tmpval);
|
||||
D(("Expanded to <%s>", tmpptr));
|
||||
break;
|
||||
|
||||
case '@':
|
||||
D(("Expanding pam item: <%s>",tmpval));
|
||||
tmpptr = _pam_get_item_byname(pamh, tmpval);
|
||||
D(("Expanded to <%s>", tmpptr));
|
||||
break;
|
||||
|
||||
default:
|
||||
D(("Impossible error, type == <%c>", type));
|
||||
_log_err(LOG_CRIT, "Impossible error, type == <%c>", type);
|
||||
return PAM_ABORT;
|
||||
} /* switch */
|
||||
|
||||
if (tmpptr) {
|
||||
if ((strlen(tmp) + strlen(tmpptr)) < MAX_ENV) {
|
||||
strcat(tmp, tmpptr);
|
||||
} else {
|
||||
/* is it really a good idea to try to log this? */
|
||||
D(("Variable buffer overflow: <%s> + <%s>", tmp, tmpptr));
|
||||
_log_err(LOG_ERR, "Variable buffer overflow: <%s> + <%s>", tmp, tmpptr);
|
||||
}
|
||||
}
|
||||
} /* if ('{' != *orig++) */
|
||||
} else { /* if ( '$' == *orig || '@' == *orig) */
|
||||
if ((strlen(tmp) + 1) < MAX_ENV) {
|
||||
tmp[strlen(tmp)] = *orig++; /* Note the increment */
|
||||
} else {
|
||||
/* is it really a good idea to try to log this? */
|
||||
D(("Variable buffer overflow: <%s> + <%s>", tmp, tmpptr));
|
||||
_log_err(LOG_ERR, "Variable buffer overflow: <%s> + <%s>", tmp, tmpptr);
|
||||
}
|
||||
}
|
||||
} /* for (;*orig;) */
|
||||
|
||||
if (strlen(tmp) > strlen(*value)) {
|
||||
free(*value);
|
||||
if ((*value = malloc(strlen(tmp) +1)) == NULL) {
|
||||
D(("Couldn't malloc %d bytes for expanded var", strlen(tmp)+1));
|
||||
_log_err(LOG_ERR,"Couldn't malloc %d bytes for expanded var",
|
||||
strlen(tmp)+1);
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
}
|
||||
strcpy(*value, tmp);
|
||||
memset(tmp,'\0',sizeof(tmp));
|
||||
D(("Exit."));
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
static const char * _pam_get_item_byname(pam_handle_t *pamh, const char *name)
|
||||
{
|
||||
/*
|
||||
* This function just allows me to use names as given in the config
|
||||
* file and translate them into the appropriate PAM_ITEM macro
|
||||
*/
|
||||
|
||||
int item;
|
||||
const char *itemval;
|
||||
|
||||
D(("Called."));
|
||||
if (strcmp(name, "PAM_USER") == 0) {
|
||||
item = PAM_USER;
|
||||
} else if (strcmp(name, "PAM_USER_PROMPT") == 0) {
|
||||
item = PAM_USER_PROMPT;
|
||||
} else if (strcmp(name, "PAM_TTY") == 0) {
|
||||
item = PAM_TTY;
|
||||
} else if (strcmp(name, "PAM_RUSER") == 0) {
|
||||
item = PAM_RUSER;
|
||||
} else if (strcmp(name, "PAM_RHOST") == 0) {
|
||||
item = PAM_RHOST;
|
||||
} else {
|
||||
D(("Unknown PAM_ITEM: <%s>", name));
|
||||
_log_err(LOG_ERR, "Unknown PAM_ITEM: <%s>", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pam_get_item(pamh, item, (const void **)&itemval) != PAM_SUCCESS) {
|
||||
D(("pam_get_item failed"));
|
||||
return NULL; /* let pam_get_item() log the error */
|
||||
}
|
||||
D(("Exit."));
|
||||
return itemval;
|
||||
}
|
||||
|
||||
static int _define_var(pam_handle_t *pamh, VAR *var)
|
||||
{
|
||||
/* We have a variable to define, this is a simple function */
|
||||
|
||||
char *envvar;
|
||||
int size, retval=PAM_SUCCESS;
|
||||
|
||||
D(("Called."));
|
||||
size = strlen(var->name)+strlen(var->value)+2;
|
||||
if ((envvar = malloc(size)) == NULL) {
|
||||
D(("Malloc fail, size = %d", size));
|
||||
_log_err(LOG_ERR, "Malloc fail, size = %d", size);
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
(void) sprintf(envvar,"%s=%s",var->name,var->value);
|
||||
retval = pam_putenv(pamh, envvar);
|
||||
free(envvar); envvar=NULL;
|
||||
D(("Exit."));
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int _undefine_var(pam_handle_t *pamh, VAR *var)
|
||||
{
|
||||
/* We have a variable to undefine, this is a simple function */
|
||||
|
||||
D(("Called and exit."));
|
||||
return pam_putenv(pamh, var->name);
|
||||
}
|
||||
|
||||
static void _clean_var(VAR *var)
|
||||
{
|
||||
if (var->name) {
|
||||
free(var->name);
|
||||
}
|
||||
if (var->defval && ("e != var->defval)) {
|
||||
free(var->defval);
|
||||
}
|
||||
if (var->override && ("e != var->override)) {
|
||||
free(var->override);
|
||||
}
|
||||
var->name = NULL;
|
||||
var->value = NULL; /* never has memory specific to it */
|
||||
var->defval = NULL;
|
||||
var->override = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* --- authentication management functions (only) --- */
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
|
||||
const char **argv)
|
||||
{
|
||||
int retval, ctrl;
|
||||
char *conf_file=NULL;
|
||||
|
||||
/*
|
||||
* this module sets environment variables read in from a file
|
||||
*/
|
||||
|
||||
D(("Called."));
|
||||
ctrl = _pam_parse(flags, argc, argv, &conf_file);
|
||||
|
||||
retval = _parse_config_file(pamh, ctrl, &conf_file);
|
||||
|
||||
/* indicate success or failure */
|
||||
|
||||
D(("Exit."));
|
||||
return retval;
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
|
||||
const char **argv)
|
||||
{
|
||||
_log_err(LOG_NOTICE, "pam_sm_acct_mgmt called inappropriatly");
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
int retval, ctrl;
|
||||
char *conf_file=NULL;
|
||||
|
||||
/*
|
||||
* this module sets environment variables read in from a file
|
||||
*/
|
||||
|
||||
D(("Called."));
|
||||
ctrl = _pam_parse(flags, argc, argv, &conf_file);
|
||||
|
||||
retval = _parse_config_file(pamh, ctrl, &conf_file);
|
||||
|
||||
/* indicate success or failure */
|
||||
|
||||
D(("Exit."));
|
||||
return retval;
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc,
|
||||
const char **argv)
|
||||
{
|
||||
D(("Called and Exit"));
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc,
|
||||
const char **argv)
|
||||
{
|
||||
_log_err(LOG_NOTICE, "pam_sm_chauthtok called inappropriatly");
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_env_modstruct = {
|
||||
"pam_env",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
pam_sm_acct_mgmt,
|
||||
pam_sm_open_session,
|
||||
pam_sm_close_session,
|
||||
pam_sm_chauthtok,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* end of module definition */
|
@ -1,72 +0,0 @@
|
||||
# $Date: 1997/04/05 06:42:35 $
|
||||
# $Author: morgan $
|
||||
# $Id: pam_env.conf-example,v 1.1 1997/04/05 06:42:35 morgan Exp $
|
||||
#
|
||||
# This is the configuration file for pam_env, a PAM module to load in
|
||||
# a configurable list of environment variables for a
|
||||
#
|
||||
# The original idea for this came from Andrew G. Morgan ...
|
||||
#<quote>
|
||||
# Mmm. Perhaps you might like to write a pam_env module that reads a
|
||||
# default environment from a file? I can see that as REALLY
|
||||
# useful... Note it would be an "auth" module that returns PAM_IGNORE
|
||||
# for the auth part and sets the environment returning PAM_SUCCESS in
|
||||
# the setcred function...
|
||||
#</quote>
|
||||
#
|
||||
# What I wanted was the REMOTEHOST variable set, purely for selfish
|
||||
# reasons, and AGM didn't want it added to the SimpleApps login
|
||||
# program (which is where I added the patch). So, my first concern is
|
||||
# that variable, from there there are numerous others that might/would
|
||||
# be useful to be set: NNTPSERVER, LESS, PATH, PAGER, MANPAGER .....
|
||||
#
|
||||
# Of course, these are a different kind of variable than REMOTEHOST in
|
||||
# that they are things that are likely to be configured by
|
||||
# administrators rather than set by logging in, how to treat them both
|
||||
# in the same config file?
|
||||
#
|
||||
# Here is my idea:
|
||||
#
|
||||
# Each line starts with the variable name, there are then two possible
|
||||
# options for each variable DEFAULT and OVERRIDE.
|
||||
# DEFAULT allows and administrator to set the value of the
|
||||
# variable to some default value, if none is supplied then the empty
|
||||
# string is assumed. The OVERRIDE option tells pam_env that it should
|
||||
# enter in its value (overriding the default value) if there is one
|
||||
# to use. OVERRIDE is not used, "" is assumed and no override will be
|
||||
# done.
|
||||
#
|
||||
# VARIABLE [DEFAULT=[value]] [OVERRIDE=[value]]
|
||||
#
|
||||
# (Possibly non-existent) environment variables may be used in values
|
||||
# using the ${string} syntax and (possibly non-existent) PAM_ITEMs may
|
||||
# be used in values using the @{string} syntax. Both the $ and @
|
||||
# characters can be backslash escaped to be used as literal values
|
||||
# values can be delimited with "", escaped " not supported.
|
||||
#
|
||||
#
|
||||
# First, some special variables
|
||||
#
|
||||
# Set the REMOTEHOST variable for any hosts that are remote, default
|
||||
# to "localhost" rather than not being set at all
|
||||
#REMOTEHOST DEFAULT=localhost OVERRIDE=@{PAM_RHOST}
|
||||
#
|
||||
# Set the DISPLAY variable if it seems reasonable
|
||||
#DISPLAY DEFAULT=${REMOTEHOST}:0.0 OVERRIDE=${DISPLAY}
|
||||
#
|
||||
#
|
||||
# Now some simple variables
|
||||
#
|
||||
#PAGER DEFAULT=less
|
||||
#MANPAGER DEFAULT=less
|
||||
#LESS DEFAULT="M q e h15 z23 b80"
|
||||
#NNTPSERVER DEFAULT=localhost
|
||||
#PATH DEFAULT=${HOME}/bin:/usr/local/bin:/bin\
|
||||
#:/usr/bin:/usr/local/bin/X11:/usr/bin/X11
|
||||
#
|
||||
# silly examples of escaped variables, just to show how they work.
|
||||
#
|
||||
#DOLLAR DEFAULT=\$
|
||||
#DOLLARDOLLAR DEFAULT= OVERRIDE=\$${DOLLAR}
|
||||
#DOLLARPLUS DEFAULT=\${REMOTEHOST}${REMOTEHOST}
|
||||
#ATSIGN DEFAULT="" OVERRIDE=\@
|
@ -1,150 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.10 1997/04/05 06:41:09 morgan Exp $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.10 1997/04/05 06:41:09 morgan
|
||||
# fakeroot
|
||||
#
|
||||
# Revision 1.9 1997/02/15 18:58:48 morgan
|
||||
# fixed bash syntax
|
||||
#
|
||||
# Revision 1.8 1997/01/04 20:24:29 morgan
|
||||
# don't compile on solaris, make -> $(MAKE)
|
||||
#
|
||||
# Revision 1.7 1996/11/10 20:12:09 morgan
|
||||
# cross platform support
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11
|
||||
#
|
||||
|
||||
ifeq ($(OS),solaris)
|
||||
|
||||
include ../dont_makefile
|
||||
|
||||
else
|
||||
|
||||
TITLE=pam_filter
|
||||
FILTERS=upperLOWER
|
||||
FILTERSDIR=$(SUPLEMENTED)/pam_filter
|
||||
export FILTERSDIR
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
#
|
||||
# this is where we compile this module
|
||||
#
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register filters
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
filters:
|
||||
@for i in $(FILTERS) ; do \
|
||||
if [ -d $$i ]; then \
|
||||
$(MAKE) -C $$i all ; \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
@for i in $(FILTERS) ; do \
|
||||
if [ -d $$i ]; then \
|
||||
$(MAKE) -C $$i install ; \
|
||||
fi ; \
|
||||
done
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
$(MKDIR) $(FAKEROOT)$(INCLUDED)
|
||||
$(INSTALL) -m 644 include/pam_filter.h $(FAKEROOT)$(INCLUDED)
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
rm -f $(FAKEROOT)$(INCLUDED)/pam_filter.h
|
||||
@for i in $(FILTERS) ; do \
|
||||
if [ -d $$i ]; then \
|
||||
$(MAKE) -C $$i remove ; \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
lclean:
|
||||
rm -f $(LIBSHARED) $(LIBOBJD) $(LIBOBJS) core *~
|
||||
|
||||
clean: lclean
|
||||
@for i in $(FILTERS) ; do \
|
||||
if [ -d $$i ]; then \
|
||||
$(MAKE) -C $$i clean ; \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
extraclean: lclean
|
||||
@rm -f *.a *.o *.so *.bak
|
||||
for i in $(FILTERS) ; do \
|
||||
if [ -d $$i ]; then \
|
||||
$(MAKE) -C $$i extraclean ; \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
endif
|
@ -1,94 +0,0 @@
|
||||
#
|
||||
# $Id: README,v 1.5 1996/12/01 02:53:08 morgan Exp $
|
||||
#
|
||||
# This describes the behavior of this module with respect to the
|
||||
# /etc/pam.conf file.
|
||||
#
|
||||
# writen by Andrew Morgan <morgan@parc.power.net>
|
||||
#
|
||||
|
||||
This module is intended to be a platform for providing access to all
|
||||
of the input/output that passes between the user and the application.
|
||||
It is only suitable for tty-based and (stdin/stdout) applications. And
|
||||
is only known to work on Linux based systems.
|
||||
|
||||
The action of the module is dictated by the arguments it is given in
|
||||
the pam.conf file.
|
||||
|
||||
recognized flags are:
|
||||
|
||||
debug print some information to syslog(3)
|
||||
|
||||
new_term set the PAM_TTY item to the new filtered
|
||||
terminal (the default is to set it
|
||||
to be that of the users terminal)
|
||||
|
||||
non_term don't try to set the PAM_TTY item
|
||||
|
||||
run1/run2 these arguments indicate that the
|
||||
module should separate the application
|
||||
from the user and insert a filter
|
||||
program between them. The pathname of
|
||||
the filter program follows the 'runN'
|
||||
argument. Arguments that follow this
|
||||
pathname are passed as arguments to
|
||||
the filter program.
|
||||
|
||||
The distinction between run1 and run2
|
||||
is which of the two functions of
|
||||
the given management-type triggers the
|
||||
execution of the indicated filter.
|
||||
|
||||
type: run1 run2
|
||||
----- ---- ----
|
||||
|
||||
auth pam_sm_authenticate pam_sm_setcred
|
||||
|
||||
account [ pam_sm_acct_mgmt (either is good) ]
|
||||
|
||||
session pam_sm_open_session pam_sm_close_session
|
||||
|
||||
password pam_sm_chauthtok/PRELIM pam_sm_chauthtok/UPDATE
|
||||
|
||||
Note, in the case of 'password' PRELIM/UPDATE indicates which of the
|
||||
two calls to pam_sm_chauthtok from libpam (not the application) will
|
||||
trigger the filter.
|
||||
|
||||
What a filter program should expect:
|
||||
------------------------------------
|
||||
|
||||
Definitions for filter programs (which may be locally designed) are
|
||||
contained in the <security/pam_filter.h> file.
|
||||
|
||||
Arguments are not passed to the filter on the command line, since this
|
||||
is plainly visible when a user types 'ps -a'. Instead they are passed
|
||||
as the filter's environment. Other information is passed in this way
|
||||
too.
|
||||
|
||||
Here is a list of the environment variables that a filter should
|
||||
expect:
|
||||
|
||||
ARGS="filter_path_name argument list"
|
||||
SERVICE="service_name" (as it appears in /etc/pam.conf)
|
||||
USER="username"
|
||||
TYPE="module_fn" (the name of the function in pam_filter.so
|
||||
that invoked the filter)
|
||||
|
||||
[This list is likely to grow. If you want something added, email me!]
|
||||
|
||||
Among other things this module is intended to provide a useful means
|
||||
of logging the activity of users in as discrete a manner as possible.
|
||||
|
||||
Existing filters:
|
||||
-----------------
|
||||
|
||||
Currently, there is a single supplied filter (upperLOWER). The effect
|
||||
of using this filter is to transpose upper and lower case letters
|
||||
between the user and the application. This is really annoying when you
|
||||
try the 'xsh' example application! ;)
|
||||
|
||||
TODO: provide more filters...
|
||||
Decide if providing stderr interception is really overkill.
|
||||
|
||||
Andrew G. Morgan <morgan@parc.power.net> 1996/5/27
|
||||
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* $Id: pam_filter.h,v 1.2 1997/02/15 19:09:09 morgan Exp $
|
||||
*
|
||||
* this file is associated with the Linux-PAM filter module.
|
||||
* it was written by Andrew G. Morgan <morgan@parc.power.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PAM_FILTER_H
|
||||
#define PAM_FILTER_H
|
||||
|
||||
#include <sys/file.h>
|
||||
|
||||
/*
|
||||
* this will fail if there is some problem with these file descriptors
|
||||
* being allocated by the pam_filter Linux-PAM module. The numbers
|
||||
* here are thought safe, but the filter developer should use the
|
||||
* macros, as these numbers are subject to change.
|
||||
*
|
||||
* The APPXXX_FILENO file descriptors are the STDIN/OUT/ERR_FILENO of the
|
||||
* application. The filter uses the STDIN/OUT/ERR_FILENO's to converse
|
||||
* with the user, passes (modified) user input to the application via
|
||||
* APPIN_FILENO, and receives application output from APPOUT_FILENO/ERR.
|
||||
*/
|
||||
|
||||
#define APPIN_FILENO 3 /* write here to give application input */
|
||||
#define APPOUT_FILENO 4 /* read here to get application output */
|
||||
#define APPERR_FILENO 5 /* read here to get application errors */
|
||||
|
||||
#define APPTOP_FILE 6 /* used by select */
|
||||
|
||||
#endif
|
@ -1,747 +0,0 @@
|
||||
/*
|
||||
* $Id: pam_filter.c,v 1.9 1997/02/15 19:07:49 morgan Exp morgan $
|
||||
*
|
||||
* $Log: pam_filter.c,v $
|
||||
* Revision 1.9 1997/02/15 19:07:49 morgan
|
||||
* fixed email
|
||||
*
|
||||
* Revision 1.8 1996/11/10 20:59:23 morgan
|
||||
* gcc warning removed
|
||||
*
|
||||
* Revision 1.7 1996/07/08 00:01:17 morgan
|
||||
* set the PAM_TTY item now
|
||||
*
|
||||
* Revision 1.6 1996/06/02 08:08:19 morgan
|
||||
* completely re-written
|
||||
*
|
||||
*
|
||||
* written by Andrew Morgan <morgan@transmeta.com> with much help from
|
||||
* Richard Stevens' UNIX Network Programming book.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termio.h>
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
#define PAM_SM_ACCOUNT
|
||||
#define PAM_SM_SESSION
|
||||
#define PAM_SM_PASSWORD
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/pam_filter.h>
|
||||
|
||||
/* ------ some tokens used for convenience throughout this file ------- */
|
||||
|
||||
#define FILTER_DEBUG 01
|
||||
#define FILTER_RUN1 02
|
||||
#define FILTER_RUN2 04
|
||||
#define NEW_TERM 010
|
||||
#define NON_TERM 020
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* log errors */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void _pam_log(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("pam_filter", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
#define TERMINAL_LEN 12
|
||||
|
||||
static int master(char *terminal)
|
||||
/*
|
||||
* try to open all of the terminals in sequence return first free one,
|
||||
* or -1
|
||||
*/
|
||||
{
|
||||
const char ptys[] = "pqrs", *pty = ptys;
|
||||
const char hexs[] = "0123456789abcdef", *hex;
|
||||
struct stat tstat;
|
||||
int fd;
|
||||
|
||||
strcpy(terminal, "/dev/pty??");
|
||||
|
||||
while (*pty) { /* step through four types */
|
||||
terminal[8] = *pty++;
|
||||
terminal[9] = '0';
|
||||
if (stat(terminal,&tstat) < 0) {
|
||||
_pam_log(LOG_WARNING, "unknown pseudo terminal; %s", terminal);
|
||||
break;
|
||||
}
|
||||
for (hex = hexs; *hex; ) { /* step through 16 of these */
|
||||
terminal[9] = *hex++;
|
||||
if ((fd = open(terminal, O_RDWR)) >= 0) {
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* no terminal found */
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int process_args(pam_handle_t *pamh
|
||||
, int argc, const char **argv, const char *type
|
||||
, char ***evp, const char **filtername)
|
||||
{
|
||||
int ctrl=0;
|
||||
|
||||
while (argc-- > 0) {
|
||||
if (strcmp("debug",*argv) == 0) {
|
||||
ctrl |= FILTER_DEBUG;
|
||||
} else if (strcmp("new_term",*argv) == 0) {
|
||||
ctrl |= NEW_TERM;
|
||||
} else if (strcmp("non_term",*argv) == 0) {
|
||||
ctrl |= NON_TERM;
|
||||
} else if (strcmp("run1",*argv) == 0) {
|
||||
ctrl |= FILTER_RUN1;
|
||||
if (argc <= 0) {
|
||||
_pam_log(LOG_ALERT,"no run filter supplied");
|
||||
} else
|
||||
break;
|
||||
} else if (strcmp("run2",*argv) == 0) {
|
||||
ctrl |= FILTER_RUN2;
|
||||
if (argc <= 0) {
|
||||
_pam_log(LOG_ALERT,"no run filter supplied");
|
||||
} else
|
||||
break;
|
||||
} else {
|
||||
_pam_log(LOG_ERR, "unrecognized option: %s (ignored)", *argv);
|
||||
}
|
||||
++argv; /* step along list */
|
||||
}
|
||||
|
||||
if (argc < 0) {
|
||||
/* there was no reference to a filter */
|
||||
*filtername = NULL;
|
||||
*evp = NULL;
|
||||
} else {
|
||||
char **levp;
|
||||
const char *tmp;
|
||||
int i,size;
|
||||
|
||||
*filtername = *++argv;
|
||||
if (ctrl & FILTER_DEBUG) {
|
||||
_pam_log(LOG_DEBUG,"will run filter %s\n", *filtername);
|
||||
}
|
||||
|
||||
levp = (char **) malloc(5*sizeof(char *));
|
||||
if (levp == NULL) {
|
||||
_pam_log(LOG_CRIT,"no memory for environment of filter");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (size=i=0; i<argc; ++i) {
|
||||
size += strlen(argv[i])+1;
|
||||
}
|
||||
|
||||
/* the "ARGS" variable */
|
||||
|
||||
#define ARGS_OFFSET 5 /* sizeof("ARGS="); */
|
||||
#define ARGS_NAME "ARGS="
|
||||
|
||||
size += ARGS_OFFSET;
|
||||
|
||||
levp[0] = (char *) malloc(size);
|
||||
if (levp[0] == NULL) {
|
||||
_pam_log(LOG_CRIT,"no memory for filter arguments");
|
||||
if (levp) {
|
||||
free(levp);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(levp[0],ARGS_NAME,ARGS_OFFSET);
|
||||
for (i=0,size=ARGS_OFFSET; i<argc; ++i) {
|
||||
strcpy(levp[0]+size, argv[i]);
|
||||
size += strlen(argv[i]);
|
||||
levp[0][size++] = ' ';
|
||||
}
|
||||
levp[0][--size] = '\0'; /* <NUL> terminate */
|
||||
|
||||
/* the "SERVICE" variable */
|
||||
|
||||
#define SERVICE_OFFSET 8 /* sizeof("SERVICE="); */
|
||||
#define SERVICE_NAME "SERVICE="
|
||||
|
||||
pam_get_item(pamh, PAM_SERVICE, (const void **)&tmp);
|
||||
size = SERVICE_OFFSET+strlen(tmp);
|
||||
|
||||
levp[1] = (char *) malloc(size+1);
|
||||
if (levp[1] == NULL) {
|
||||
_pam_log(LOG_CRIT,"no memory for service name");
|
||||
if (levp) {
|
||||
free(levp[0]);
|
||||
free(levp);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(levp[1],SERVICE_NAME,SERVICE_OFFSET);
|
||||
strcpy(levp[1]+SERVICE_OFFSET, tmp);
|
||||
levp[1][size] = '\0'; /* <NUL> terminate */
|
||||
|
||||
/* the "USER" variable */
|
||||
|
||||
#define USER_OFFSET 5 /* sizeof("USER="); */
|
||||
#define USER_NAME "USER="
|
||||
|
||||
pam_get_user(pamh, &tmp, NULL);
|
||||
if (tmp == NULL) {
|
||||
tmp = "<unknown>";
|
||||
}
|
||||
size = USER_OFFSET+strlen(tmp);
|
||||
|
||||
levp[2] = (char *) malloc(size+1);
|
||||
if (levp[2] == NULL) {
|
||||
_pam_log(LOG_CRIT,"no memory for user's name");
|
||||
if (levp) {
|
||||
free(levp[1]);
|
||||
free(levp[0]);
|
||||
free(levp);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(levp[2],USER_NAME,USER_OFFSET);
|
||||
strcpy(levp[2]+USER_OFFSET, tmp);
|
||||
levp[2][size] = '\0'; /* <NUL> terminate */
|
||||
|
||||
/* the "USER" variable */
|
||||
|
||||
#define TYPE_OFFSET 5 /* sizeof("TYPE="); */
|
||||
#define TYPE_NAME "TYPE="
|
||||
|
||||
size = TYPE_OFFSET+strlen(type);
|
||||
|
||||
levp[3] = (char *) malloc(size+1);
|
||||
if (levp[3] == NULL) {
|
||||
_pam_log(LOG_CRIT,"no memory for type");
|
||||
if (levp) {
|
||||
free(levp[2]);
|
||||
free(levp[1]);
|
||||
free(levp[0]);
|
||||
free(levp);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(levp[3],TYPE_NAME,TYPE_OFFSET);
|
||||
strcpy(levp[3]+TYPE_OFFSET, type);
|
||||
levp[3][size] = '\0'; /* <NUL> terminate */
|
||||
|
||||
levp[4] = NULL; /* end list */
|
||||
|
||||
*evp = levp;
|
||||
}
|
||||
|
||||
if ((ctrl & FILTER_DEBUG) && *filtername) {
|
||||
char **e;
|
||||
|
||||
_pam_log(LOG_DEBUG,"filter[%s]: %s",type,*filtername);
|
||||
_pam_log(LOG_DEBUG,"environment:");
|
||||
for (e=*evp; e && *e; ++e) {
|
||||
_pam_log(LOG_DEBUG," %s",*e);
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
static void free_evp(char *evp[])
|
||||
{
|
||||
int i;
|
||||
|
||||
if (evp)
|
||||
for (i=0; i<4; ++i) {
|
||||
if (evp[i])
|
||||
free(evp[i]);
|
||||
}
|
||||
free(evp);
|
||||
}
|
||||
|
||||
static int set_filter(pam_handle_t *pamh, int flags, int ctrl
|
||||
, const char **evp, const char *filtername)
|
||||
{
|
||||
int status=-1;
|
||||
char terminal[TERMINAL_LEN];
|
||||
struct termio stored_mode; /* initial terminal mode settings */
|
||||
int fd[2], child=0, child2=0, aterminal;
|
||||
|
||||
if (filtername == NULL || *filtername != '/') {
|
||||
_pam_log(LOG_ALERT, "filtername not permitted; require full path");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
if (!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO)) {
|
||||
aterminal = 0;
|
||||
} else {
|
||||
aterminal = 1;
|
||||
}
|
||||
|
||||
if (aterminal) {
|
||||
|
||||
/* open the master pseudo terminal */
|
||||
|
||||
fd[0] = master(terminal);
|
||||
if (fd[0] < 0) {
|
||||
_pam_log(LOG_CRIT,"no master terminal");
|
||||
return PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
/* set terminal into raw mode.. remember old mode so that we can
|
||||
revert to it after the child has quit. */
|
||||
|
||||
/* this is termio terminal handling... */
|
||||
|
||||
if (ioctl(STDIN_FILENO, TCGETA, (char *) &stored_mode ) < 0) {
|
||||
/* in trouble, so close down */
|
||||
close(fd[0]);
|
||||
_pam_log(LOG_CRIT, "couldn't copy terminal mode");
|
||||
return PAM_ABORT;
|
||||
} else {
|
||||
struct termio t_mode = stored_mode;
|
||||
|
||||
t_mode.c_iflag = 0; /* no input control */
|
||||
t_mode.c_oflag &= ~OPOST; /* no ouput post processing */
|
||||
|
||||
/* no signals, canonical input, echoing, upper/lower output */
|
||||
t_mode.c_lflag &= ~(ISIG|ICANON|ECHO|XCASE);
|
||||
t_mode.c_cflag &= ~(CSIZE|PARENB); /* no parity */
|
||||
t_mode.c_cflag |= CS8; /* 8 bit chars */
|
||||
|
||||
t_mode.c_cc[VMIN] = 1; /* number of chars to satisfy a read */
|
||||
t_mode.c_cc[VTIME] = 0; /* 0/10th second for chars */
|
||||
|
||||
if (ioctl(STDIN_FILENO, TCSETA, (char *) &t_mode) < 0) {
|
||||
close(fd[0]);
|
||||
_pam_log(LOG_WARNING, "couldn't put terminal in RAW mode");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: Unlike the stream socket case here the child
|
||||
* opens the slave terminal as fd[1] *after* the fork...
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
|
||||
/*
|
||||
* not a terminal line so just open a stream socket fd[0-1]
|
||||
* both set...
|
||||
*/
|
||||
|
||||
if ( socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0 ) {
|
||||
_pam_log(LOG_CRIT,"couldn't open a stream pipe");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
/* start child process */
|
||||
|
||||
if ( (child = fork()) < 0 ) {
|
||||
|
||||
_pam_log(LOG_WARNING,"first fork failed");
|
||||
if (aterminal) {
|
||||
(void) ioctl(STDIN_FILENO, TCSETA, (char *) &stored_mode);
|
||||
}
|
||||
|
||||
return PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
if ( child == 0 ) { /* child process *is* application */
|
||||
|
||||
if (aterminal) {
|
||||
|
||||
/* close the controlling tty */
|
||||
|
||||
#if defined(__hpux) && defined(O_NOCTTY)
|
||||
int t = open("/dev/tty", O_RDWR|O_NOCTTY);
|
||||
#else
|
||||
int t = open("/dev/tty",O_RDWR);
|
||||
if (t > 0) {
|
||||
(void) ioctl(t, TIOCNOTTY, NULL);
|
||||
close(t);
|
||||
}
|
||||
#endif /* defined(__hpux) && defined(O_NOCTTY) */
|
||||
|
||||
/* make this process it's own process leader */
|
||||
if (setsid() == -1) {
|
||||
_pam_log(LOG_WARNING,"child cannot become new session");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* find slave's name */
|
||||
terminal[5] = 't'; /* want to open slave terminal */
|
||||
fd[1] = open(terminal, O_RDWR);
|
||||
close(fd[0]); /* process is the child -- uses line fd[1] */
|
||||
|
||||
if (fd[1] < 0) {
|
||||
_pam_log(LOG_WARNING,"cannot open slave terminal; %s"
|
||||
,terminal);
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* initialize the child's terminal to be the way the
|
||||
parent's was before we set it into RAW mode */
|
||||
|
||||
if (ioctl(fd[1], TCSETA, (char *) &stored_mode) < 0) {
|
||||
_pam_log(LOG_WARNING,"cannot set slave terminal mode; %s"
|
||||
,terminal);
|
||||
close(fd[1]);
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* nothing to do for a simple stream socket */
|
||||
|
||||
}
|
||||
|
||||
/* re-assign the stdin/out to fd[1] <- (talks to filter). */
|
||||
|
||||
if ( dup2(fd[1],STDIN_FILENO) != STDIN_FILENO ||
|
||||
dup2(fd[1],STDOUT_FILENO) != STDOUT_FILENO ||
|
||||
dup2(fd[1],STDERR_FILENO) != STDERR_FILENO ) {
|
||||
_pam_log(LOG_WARNING
|
||||
,"unable to re-assign STDIN/OUT/ERR...'s");
|
||||
close(fd[1]);
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* make sure that file descriptors survive 'exec's */
|
||||
|
||||
if ( fcntl(STDIN_FILENO, F_SETFD, 0) ||
|
||||
fcntl(STDOUT_FILENO,F_SETFD, 0) ||
|
||||
fcntl(STDERR_FILENO,F_SETFD, 0) ) {
|
||||
_pam_log(LOG_WARNING
|
||||
,"unable to re-assign STDIN/OUT/ERR...'s");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* now the user input is read from the parent/filter: forget fd */
|
||||
|
||||
close(fd[1]);
|
||||
|
||||
/* the current process is now aparently working with filtered
|
||||
stdio/stdout/stderr --- success! */
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* process is the parent here. So we can close the application's
|
||||
* input/output
|
||||
*/
|
||||
|
||||
close(fd[1]);
|
||||
|
||||
/* Clear out passwords... there is a security problem here in
|
||||
* that this process never executes pam_end. Consequently, any
|
||||
* other sensitive data in this process is *not* explicitly
|
||||
* overwritten, before the process terminates */
|
||||
|
||||
(void) pam_set_item(pamh, PAM_AUTHTOK, NULL);
|
||||
(void) pam_set_item(pamh, PAM_OLDAUTHTOK, NULL);
|
||||
|
||||
/* fork a copy of process to run the actual filter executable */
|
||||
|
||||
if ( (child2 = fork()) < 0 ) {
|
||||
|
||||
_pam_log(LOG_WARNING,"filter fork failed");
|
||||
child2 = 0;
|
||||
|
||||
} else if ( child2 == 0 ) { /* exec the child filter */
|
||||
|
||||
if ( dup2(fd[0],APPIN_FILENO) != APPIN_FILENO ||
|
||||
dup2(fd[0],APPOUT_FILENO) != APPOUT_FILENO ||
|
||||
dup2(fd[0],APPERR_FILENO) != APPERR_FILENO ) {
|
||||
_pam_log(LOG_WARNING
|
||||
,"unable to re-assign APPIN/OUT/ERR...'s");
|
||||
close(fd[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* make sure that file descriptors survive 'exec's */
|
||||
|
||||
if ( fcntl(APPIN_FILENO, F_SETFD, 0) == -1 ||
|
||||
fcntl(APPOUT_FILENO,F_SETFD, 0) == -1 ||
|
||||
fcntl(APPERR_FILENO,F_SETFD, 0) == -1 ) {
|
||||
_pam_log(LOG_WARNING
|
||||
,"unable to retain APPIN/OUT/ERR...'s");
|
||||
close(APPIN_FILENO);
|
||||
close(APPOUT_FILENO);
|
||||
close(APPERR_FILENO);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* now the user input is read from the parent through filter */
|
||||
|
||||
execle(filtername, "<pam_filter>", NULL, evp);
|
||||
|
||||
/* getting to here is an error */
|
||||
|
||||
_pam_log(LOG_ALERT, "filter: %s, not executable", filtername);
|
||||
|
||||
} else { /* wait for either of the two children to exit */
|
||||
|
||||
while (child && child2) { /* loop if there are two children */
|
||||
int lstatus=0;
|
||||
int chid;
|
||||
|
||||
chid = wait(&lstatus);
|
||||
if (chid == child) {
|
||||
|
||||
if (WIFEXITED(lstatus)) { /* exited ? */
|
||||
status = WEXITSTATUS(lstatus);
|
||||
} else if (WIFSIGNALED(lstatus)) { /* killed ? */
|
||||
status = -1;
|
||||
} else
|
||||
continue; /* just stopped etc.. */
|
||||
child = 0; /* the child has exited */
|
||||
|
||||
} else if (chid == child2) {
|
||||
/*
|
||||
* if the filter has exited. Let the child die
|
||||
* naturally below
|
||||
*/
|
||||
if (WIFEXITED(lstatus) || WIFSIGNALED(lstatus))
|
||||
child2 = 0;
|
||||
} else {
|
||||
|
||||
_pam_log(LOG_ALERT
|
||||
,"programming error <chid=%d,lstatus=%x>: "
|
||||
__FILE__ " line %d"
|
||||
, lstatus, __LINE__ );
|
||||
child = child2 = 0;
|
||||
status = -1;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close(fd[0]);
|
||||
|
||||
/* if there is something running, wait for it to exit */
|
||||
|
||||
while (child || child2) {
|
||||
int lstatus=0;
|
||||
int chid;
|
||||
|
||||
chid = wait(&lstatus);
|
||||
|
||||
if (child && chid == child) {
|
||||
|
||||
if (WIFEXITED(lstatus)) { /* exited ? */
|
||||
status = WEXITSTATUS(lstatus);
|
||||
} else if (WIFSIGNALED(lstatus)) { /* killed ? */
|
||||
status = -1;
|
||||
} else
|
||||
continue; /* just stopped etc.. */
|
||||
child = 0; /* the child has exited */
|
||||
|
||||
} else if (child2 && chid == child2) {
|
||||
|
||||
if (WIFEXITED(lstatus) || WIFSIGNALED(lstatus))
|
||||
child2 = 0;
|
||||
|
||||
} else {
|
||||
|
||||
_pam_log(LOG_ALERT
|
||||
,"programming error <chid=%d,lstatus=%x>: "
|
||||
__FILE__ " line %d"
|
||||
, lstatus, __LINE__ );
|
||||
child = child2 = 0;
|
||||
status = -1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (aterminal) {
|
||||
/* reset to initial terminal mode */
|
||||
(void) ioctl(STDIN_FILENO, TCSETA, (char *) &stored_mode);
|
||||
}
|
||||
|
||||
if (ctrl & FILTER_DEBUG) {
|
||||
_pam_log(LOG_DEBUG,"parent process exited"); /* clock off */
|
||||
}
|
||||
|
||||
/* quit the parent process, returning the child's exit status */
|
||||
|
||||
exit(status);
|
||||
}
|
||||
|
||||
static int set_the_terminal(pam_handle_t *pamh)
|
||||
{
|
||||
const char *tty;
|
||||
|
||||
if (pam_get_item(pamh, PAM_TTY, (const void **)&tty) != PAM_SUCCESS
|
||||
|| tty == NULL) {
|
||||
tty = ttyname(STDIN_FILENO);
|
||||
if (tty == NULL) {
|
||||
_pam_log(LOG_ERR, "couldn't get the tty name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
if (pam_set_item(pamh, PAM_TTY, tty) != PAM_SUCCESS) {
|
||||
_pam_log(LOG_ERR, "couldn't set tty name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
}
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
static int need_a_filter(pam_handle_t *pamh
|
||||
, int flags, int argc, const char **argv
|
||||
, const char *name, int which_run)
|
||||
{
|
||||
int ctrl;
|
||||
char **evp;
|
||||
const char *filterfile;
|
||||
int retval;
|
||||
|
||||
ctrl = process_args(pamh, argc, argv, name, &evp, &filterfile);
|
||||
if (ctrl == -1) {
|
||||
return PAM_AUTHINFO_UNAVAIL;
|
||||
}
|
||||
|
||||
/* set the tty to the old or the new one? */
|
||||
|
||||
if (!(ctrl & NON_TERM) && !(ctrl & NEW_TERM)) {
|
||||
retval = set_the_terminal(pamh);
|
||||
if (retval != PAM_SUCCESS) {
|
||||
_pam_log(LOG_ERR, "tried and failed to set PAM_TTY");
|
||||
}
|
||||
} else {
|
||||
retval = PAM_SUCCESS; /* nothing to do which is always a success */
|
||||
}
|
||||
|
||||
if (retval == PAM_SUCCESS && (ctrl & which_run)) {
|
||||
retval = set_filter(pamh, flags, ctrl
|
||||
, (const char **)evp, filterfile);
|
||||
}
|
||||
|
||||
if (retval == PAM_SUCCESS
|
||||
&& !(ctrl & NON_TERM) && (ctrl & NEW_TERM)) {
|
||||
retval = set_the_terminal(pamh);
|
||||
if (retval != PAM_SUCCESS) {
|
||||
_pam_log(LOG_ERR
|
||||
, "tried and failed to set new terminal as PAM_TTY");
|
||||
}
|
||||
}
|
||||
|
||||
free_evp(evp);
|
||||
|
||||
if (ctrl & FILTER_DEBUG) {
|
||||
_pam_log(LOG_DEBUG, "filter/%s, returning %d", name, retval);
|
||||
_pam_log(LOG_DEBUG, "[%s]", pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* ----------------- public functions ---------------- */
|
||||
|
||||
/*
|
||||
* here are the advertised access points ...
|
||||
*/
|
||||
|
||||
/* ------------------ authentication ----------------- */
|
||||
|
||||
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh
|
||||
, int flags, int argc, const char **argv)
|
||||
{
|
||||
return need_a_filter(pamh, flags, argc, argv
|
||||
, "authenticate", FILTER_RUN1);
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
|
||||
, int argc, const char **argv)
|
||||
{
|
||||
return need_a_filter(pamh, flags, argc, argv, "setcred", FILTER_RUN2);
|
||||
}
|
||||
|
||||
/* --------------- account management ---------------- */
|
||||
|
||||
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
|
||||
const char **argv)
|
||||
{
|
||||
return need_a_filter(pamh, flags, argc, argv
|
||||
, "setcred", FILTER_RUN1|FILTER_RUN2 );
|
||||
}
|
||||
|
||||
/* --------------- session management ---------------- */
|
||||
|
||||
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags
|
||||
, int argc, const char **argv)
|
||||
{
|
||||
return need_a_filter(pamh, flags, argc, argv
|
||||
, "open_session", FILTER_RUN1);
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags
|
||||
, int argc, const char **argv)
|
||||
{
|
||||
return need_a_filter(pamh, flags, argc, argv
|
||||
, "close_session", FILTER_RUN2);
|
||||
}
|
||||
|
||||
/* --------- updating authentication tokens --------- */
|
||||
|
||||
|
||||
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags
|
||||
, int argc, const char **argv)
|
||||
{
|
||||
int runN;
|
||||
|
||||
if (flags & PAM_PRELIM_CHECK)
|
||||
runN = FILTER_RUN1;
|
||||
else if (flags & PAM_UPDATE_AUTHTOK)
|
||||
runN = FILTER_RUN2;
|
||||
else {
|
||||
_pam_log(LOG_ERR, "unknown flags for chauthtok (0x%X)", flags);
|
||||
return PAM_TRY_AGAIN;
|
||||
}
|
||||
|
||||
return need_a_filter(pamh, flags, argc, argv, "chauthtok", runN);
|
||||
}
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* ------------ stuff for static modules ------------ */
|
||||
|
||||
struct pam_module _pam_filter_modstruct = {
|
||||
"pam_filter",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
pam_sm_acct_mgmt,
|
||||
pam_sm_open_session,
|
||||
pam_sm_close_session,
|
||||
pam_sm_chauthtok,
|
||||
};
|
||||
|
||||
#endif
|
@ -1,58 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.5 1997/04/05 06:41:35 morgan Exp $
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.5 1997/04/05 06:41:35 morgan
|
||||
# fakeroot
|
||||
#
|
||||
# Revision 1.4 1997/01/04 20:25:04 morgan
|
||||
# removed need for make
|
||||
#
|
||||
# Revision 1.3 1996/11/10 20:13:08 morgan
|
||||
# email address
|
||||
#
|
||||
# Revision 1.2 1996/11/10 20:12:24 morgan
|
||||
# cross platform support
|
||||
#
|
||||
# Revision 1.1 1996/06/02 08:17:02 morgan
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
# This directory contains a pam_filter filter executable
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/3/11
|
||||
#
|
||||
|
||||
TITLE=upperLOWER
|
||||
|
||||
#
|
||||
|
||||
OBJS = $(TITLE).o
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
|
||||
all: $(TITLE)
|
||||
|
||||
$(TITLE): $(OBJS)
|
||||
$(CC) -o $(TITLE) $(OBJS)
|
||||
strip $(TITLE)
|
||||
|
||||
install:
|
||||
$(MKDIR) $(FAKEROOT)$(FILTERSDIR)
|
||||
$(INSTALL) -m 511 $(TITLE) $(FAKEROOT)$(FILTERSDIR)
|
||||
|
||||
remove:
|
||||
cd $(FAKEROOT)$(FILTERSDIR) && rm -f $(TITLE)
|
||||
|
||||
clean:
|
||||
rm -f $(TITLE) $(OBJS) core *~
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.bak
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,160 +0,0 @@
|
||||
/*
|
||||
* $Id: upperLOWER.c,v 1.1 1996/06/02 08:17:02 morgan Exp $
|
||||
*
|
||||
* This is a sample filter program, for use with pam_filter (a module
|
||||
* provided with Linux-PAM). This filter simply transposes upper and
|
||||
* lower case letters, it is intended for demonstration purposes and
|
||||
* it serves no purpose other than to annoy the user...
|
||||
*
|
||||
* $Log: upperLOWER.c,v $
|
||||
* Revision 1.1 1996/06/02 08:17:02 morgan
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <security/pam_filter.h>
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifdef hpux
|
||||
# define log_this syslog
|
||||
#else
|
||||
static void log_this(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("upperLOWER", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
static void do_transpose(char *buffer,int len)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<len; ++i) {
|
||||
if (islower(buffer[i])) {
|
||||
buffer[i] = toupper(buffer[i]);
|
||||
} else {
|
||||
buffer[i] = tolower(buffer[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
fd_set readers;
|
||||
void (*before_user)(char *,int);
|
||||
void (*before_app)(char *,int);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(stderr,"environment :[\r\n");
|
||||
for (i=0; envp[i]; ++i) {
|
||||
fprintf(stderr,"-> %s\r\n",envp[i]);
|
||||
}
|
||||
fprintf(stderr,"]: end\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (argc != 1) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"filter invoked as conventional executable\n");
|
||||
#else
|
||||
log_this(LOG_ERR, "filter invoked as conventional executable");
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
before_user = before_app = do_transpose; /* assign filter functions */
|
||||
|
||||
/* enter a loop that deals with the input and output of the
|
||||
user.. passing it to and from the application */
|
||||
|
||||
FD_ZERO(&readers); /* initialize reading mask */
|
||||
|
||||
for (;;) {
|
||||
|
||||
FD_SET(APPOUT_FILENO, &readers); /* wake for output */
|
||||
FD_SET(APPERR_FILENO, &readers); /* wake for error */
|
||||
FD_SET(STDIN_FILENO, &readers); /* wake for input */
|
||||
|
||||
if ( select(APPTOP_FILE,&readers,NULL,NULL,NULL) < 0 ) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr,"select failed\n");
|
||||
#else
|
||||
log_this(LOG_WARNING,"select failed");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
/* application errors */
|
||||
|
||||
if ( FD_ISSET(APPERR_FILENO,&readers) ) {
|
||||
int got = read(APPERR_FILENO, buffer, BUFSIZ);
|
||||
if (got <= 0) {
|
||||
break;
|
||||
} else {
|
||||
/* translate to give to real terminal */
|
||||
if (before_user != NULL)
|
||||
before_user(buffer, got);
|
||||
if ( write(STDERR_FILENO, buffer, got) != got ) {
|
||||
log_this(LOG_WARNING,"couldn't write %d bytes?!",got);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ( FD_ISSET(APPOUT_FILENO,&readers) ) { /* app output */
|
||||
int got = read(APPOUT_FILENO, buffer, BUFSIZ);
|
||||
if (got <= 0) {
|
||||
break;
|
||||
} else {
|
||||
/* translate to give to real terminal */
|
||||
if (before_user != NULL)
|
||||
before_user(buffer, got);
|
||||
if ( write(STDOUT_FILENO, buffer, got) != got ) {
|
||||
log_this(LOG_WARNING,"couldn't write %d bytes!?",got);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( FD_ISSET(STDIN_FILENO, &readers) ) { /* user input */
|
||||
int got = read(STDIN_FILENO, buffer, BUFSIZ);
|
||||
if (got < 0) {
|
||||
log_this(LOG_WARNING,"user input junked");
|
||||
break;
|
||||
} else if (got) {
|
||||
/* translate to give to application */
|
||||
if (before_app != NULL)
|
||||
before_app(buffer, got);
|
||||
if ( write(APPIN_FILENO, buffer, got) != got ) {
|
||||
log_this(LOG_WARNING,"couldn't pass %d bytes!?",got);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* nothing received -- an error? */
|
||||
log_this(LOG_WARNING,"user input null?");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,96 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.2 1997/04/05 06:40:33 morgan Exp $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.2 1997/04/05 06:40:33 morgan
|
||||
# fakeroot
|
||||
#
|
||||
# Revision 1.1 1996/12/01 03:17:57 morgan
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/11/14
|
||||
#
|
||||
|
||||
TITLE=pam_ftp
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak dynamic/* static/*
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,20 +0,0 @@
|
||||
# $Id: README,v 1.1 1996/12/01 03:17:57 morgan Exp $
|
||||
#
|
||||
|
||||
This module is an authentication module that does not authenticate.
|
||||
Instead it always returns PAM_IGNORE, indicating that it does not want
|
||||
to affect the authentication process.
|
||||
|
||||
Its purpose is to log a message to the syslog indicating the
|
||||
pam_item's available at the time it was invoked. It is a diagnostic
|
||||
tool.
|
||||
|
||||
Recognized arguments:
|
||||
|
||||
none
|
||||
|
||||
module services provided:
|
||||
|
||||
auth _authetication and _setcred (blank)
|
||||
|
||||
Andrew Morgan
|
@ -1,295 +0,0 @@
|
||||
/* pam_ftp module */
|
||||
|
||||
/*
|
||||
* $Id: pam_ftp.c,v 1.2 1997/02/15 16:23:59 morgan Exp morgan $
|
||||
*
|
||||
* Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11
|
||||
*
|
||||
* $Log: pam_ftp.c,v $
|
||||
* Revision 1.2 1997/02/15 16:23:59 morgan
|
||||
* fixed logging to avoid a fixed buffer size
|
||||
*
|
||||
* Revision 1.1 1996/12/01 03:17:57 morgan
|
||||
* Initial revision
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#define PLEASE_ENTER_PASSWORD "Password required for %s."
|
||||
#define GUEST_LOGIN_PROMPT "Guest login ok, " \
|
||||
"send your complete e-mail address as password."
|
||||
|
||||
/* the following is a password that "can't be correct" */
|
||||
#define BLOCK_PASSWORD "\177BAD PASSWPRD\177"
|
||||
|
||||
#ifdef linux
|
||||
# define _GNU_SOURCE
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* here, we make a definition for the externally accessible function
|
||||
* in this file (this definition is required for static a module
|
||||
* but strongly encouraged generally) it is used to instruct the
|
||||
* modules include file to define the function prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
/* some syslogging */
|
||||
|
||||
static void _pam_log(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("PAM-ftp", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
static int converse(pam_handle_t *pamh, int nargs
|
||||
, struct pam_message **message
|
||||
, struct pam_response **response)
|
||||
{
|
||||
int retval;
|
||||
struct pam_conv *conv;
|
||||
|
||||
D(("begin to converse\n"));
|
||||
|
||||
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
|
||||
if ( retval == PAM_SUCCESS ) {
|
||||
|
||||
retval = conv->conv(nargs, ( const struct pam_message ** ) message
|
||||
, response, conv->appdata_ptr);
|
||||
|
||||
D(("returned from application's conversation function\n"));
|
||||
|
||||
if (retval != PAM_SUCCESS) {
|
||||
_pam_log(LOG_DEBUG, "conversation failure [%s]"
|
||||
, pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
} else {
|
||||
_pam_log(LOG_ERR, "couldn't obtain coversation function [%s]"
|
||||
, pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
D(("ready to return from module conversation\n"));
|
||||
|
||||
return retval; /* propagate error status */
|
||||
}
|
||||
|
||||
/* argument parsing */
|
||||
|
||||
#define PAM_DEBUG_ARG 01
|
||||
#define PAM_IGNORE_EMAIL 02
|
||||
#define PAM_NO_ANON 04
|
||||
|
||||
static int _pam_parse(int argc, const char **argv, char **users)
|
||||
{
|
||||
int ctrl=0;
|
||||
|
||||
/* step through arguments */
|
||||
for (ctrl=0; argc-- > 0; ++argv) {
|
||||
|
||||
/* generic options */
|
||||
|
||||
if (!strcmp(*argv,"debug"))
|
||||
ctrl |= PAM_DEBUG_ARG;
|
||||
else if (!strncmp(*argv,"users=",6)) {
|
||||
*users = x_strdup(6+*argv);
|
||||
if (*users == NULL) {
|
||||
ctrl |= PAM_NO_ANON;
|
||||
_pam_log(LOG_CRIT, "failed to duplicate user list - anon off");
|
||||
}
|
||||
} else if (!strcmp(*argv,"ignore")) {
|
||||
ctrl |= PAM_IGNORE_EMAIL;
|
||||
} else {
|
||||
_pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
/*
|
||||
* check if name is in list or default list. place users name in *_user
|
||||
* return 1 if listed 0 if not.
|
||||
*/
|
||||
|
||||
static int lookup(const char *name, char *list, const char **_user)
|
||||
{
|
||||
int anon = 0;
|
||||
|
||||
*_user = name; /* this is the default */
|
||||
if (list) {
|
||||
const char *l;
|
||||
char *x;
|
||||
|
||||
x = list;
|
||||
while ((l = strtok(x, ","))) {
|
||||
x = NULL;
|
||||
if (!strcmp(name, l)) {
|
||||
*_user = list;
|
||||
anon = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#define MAX_L 2
|
||||
static const char *l[MAX_L] = { "ftp", "anonymous" };
|
||||
int i;
|
||||
|
||||
for (i=0; i<MAX_L; ++i) {
|
||||
if (!strcmp(l[i], name)) {
|
||||
*_user = l[0];
|
||||
anon = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return anon;
|
||||
}
|
||||
|
||||
/* --- authentication management functions (only) --- */
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
int retval, anon=0, ctrl;
|
||||
const char *user;
|
||||
char *users=NULL;
|
||||
|
||||
/*
|
||||
* this module checks if the user name is ftp or annonymous. If
|
||||
* this is the case, it can set the PAM_RUSER to the entered email
|
||||
* address and SUCCEEDS, otherwise it FAILS.
|
||||
*/
|
||||
|
||||
ctrl = _pam_parse(argc, argv, &users);
|
||||
|
||||
retval = pam_get_user(pamh, &user, NULL);
|
||||
if (retval != PAM_SUCCESS || user == NULL) {
|
||||
_pam_log(LOG_ERR, "no user specified");
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
if (!(ctrl & PAM_NO_ANON)) {
|
||||
anon = lookup(user, users, &user);
|
||||
}
|
||||
|
||||
if (anon) {
|
||||
retval = pam_set_item(pamh, PAM_USER, (const void *)user);
|
||||
if (retval != PAM_SUCCESS || user == NULL) {
|
||||
_pam_log(LOG_ERR, "user resetting failed");
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* OK. we require an email address for user or the user's password.
|
||||
* - build conversation and get their input.
|
||||
*/
|
||||
|
||||
{
|
||||
struct pam_message msg[1], *mesg[1];
|
||||
struct pam_response *resp=NULL;
|
||||
const char *token;
|
||||
char *prompt=NULL;
|
||||
int i=0;
|
||||
|
||||
mesg[i] = &msg[i];
|
||||
msg[i].msg_style = PAM_PROMPT_ECHO_OFF;
|
||||
if (anon) {
|
||||
prompt = malloc(sizeof(PLEASE_ENTER_PASSWORD + strlen(user)));
|
||||
sprintf(prompt, PLEASE_ENTER_PASSWORD, user);
|
||||
msg[i].msg = prompt;
|
||||
} else {
|
||||
msg[i].msg = GUEST_LOGIN_PROMPT;
|
||||
}
|
||||
|
||||
retval = converse(pamh, ++i, mesg, &resp);
|
||||
_pam_overwrite(prompt);
|
||||
_pam_drop(prompt);
|
||||
|
||||
if (retval != PAM_SUCCESS) {
|
||||
if (resp != NULL)
|
||||
_pam_drop_reply(resp,i);
|
||||
return PAM_AUTHINFO_UNAVAIL;
|
||||
}
|
||||
|
||||
if (anon) {
|
||||
/* XXX: Some effort should be made to verify this email address! */
|
||||
|
||||
if (!(ctrl & PAM_IGNORE_EMAIL)) {
|
||||
token = strtok(resp->resp, "@");
|
||||
retval = pam_set_item(pamh, PAM_RUSER, token);
|
||||
|
||||
if (token && retval != PAM_SUCCESS) {
|
||||
token = strtok(NULL, "@");
|
||||
retval = pam_set_item(pamh, PAM_RHOST, token);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* we have a password so set AUTHTOK
|
||||
*/
|
||||
|
||||
(void) pam_set_item(pamh, PAM_AUTHTOK, resp->resp);
|
||||
|
||||
/*
|
||||
* this module failed, but the next one might succeed with
|
||||
* this password.
|
||||
*/
|
||||
|
||||
retval = PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
if (resp) { /* clean up */
|
||||
_pam_drop_reply(resp, i);
|
||||
}
|
||||
|
||||
/* success or failure */
|
||||
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_ftp_modstruct = {
|
||||
"pam_ftp",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* end of module definition */
|
@ -1,114 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.6 1997/04/05 06:39:56 morgan Exp morgan $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.6 1997/04/05 06:39:56 morgan
|
||||
# fakeroot
|
||||
#
|
||||
# Revision 1.5 1997/01/04 20:28:47 morgan
|
||||
# compile with and without libpwdb
|
||||
#
|
||||
# Revision 1.4 1996/11/10 20:13:18 morgan
|
||||
# cross platform support
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/6/11
|
||||
#
|
||||
|
||||
TITLE=pam_group
|
||||
CONFD=$(CONFIGED)/security
|
||||
export CONFD
|
||||
CONFILE=$(CONFD)/group.conf
|
||||
export CONFILE
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
DEFS=-DCONFILE=\"$(CONFILE)\"
|
||||
ifndef STATIC
|
||||
ifeq ($(HAVE_PWDBLIB),yes)
|
||||
DEFS+=-DWANT_PWDB
|
||||
ELIBS=-lpwdb
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS += $(DEFS)
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD) $(ELIBS)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS) $(ELIBS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
$(MKDIR) $(FAKEROOT)$(SCONFIGED)
|
||||
bash -f ./install_conf
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
rm -f $(FAKEROOT)$(CONFILE)
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
rm -f ./.ignore_age
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,60 +0,0 @@
|
||||
##
|
||||
## Note, to get this to work as it is currently typed you need
|
||||
##
|
||||
## 1. to run an application as root
|
||||
## 2. add the following groups to the /etc/group file:
|
||||
## floppy, games, sound
|
||||
##
|
||||
#
|
||||
# *** Please note that giving group membership on a session basis is
|
||||
# *** NOT inherently secure. If a user can create an executable that
|
||||
# *** is setgid a group that they are infrequently given membership
|
||||
# *** of, they can basically obtain group membership any time they
|
||||
# *** like. Example: games are alowed between the hours of 6pm and 6am
|
||||
# *** user joe logs in at 7pm writes a small C-program toplay.c that
|
||||
# *** invokes their favorite shell, compiles it and does
|
||||
# *** "chgrp games toplay; chmod g+s toplay". They are basically able
|
||||
# *** to play games any time... You have been warned. AGM
|
||||
#
|
||||
# this is an example configuration file for the pam_group module. Its
|
||||
# syntax is based on that of the pam_time module and (at some point in
|
||||
# the distant past was inspired by the 'shadow' package)
|
||||
#
|
||||
# the syntax of the lines is as follows:
|
||||
#
|
||||
# services;ttys;users;times;groups
|
||||
#
|
||||
# white space is ignored and lines maybe extended with '\\n' (escaped
|
||||
# newlines). From reading these comments, it is clear that
|
||||
# text following a '#' is ignored to the end of the line.
|
||||
#
|
||||
# the first four fields are described in the pam_time directory.
|
||||
# The only difference for these is how the time field is interpretted:
|
||||
# it is used to indicate "when" these groups are to be given to the user.
|
||||
#
|
||||
# groups
|
||||
# The (comma or space separated) list of groups that the user
|
||||
# inherits membership of. These groups are added if the previous
|
||||
# fields are satisfied by the user's request
|
||||
#
|
||||
|
||||
#
|
||||
# Here is a simple example: running 'xsh' on tty* (any ttyXXX device),
|
||||
# the user 'us' is given access to the floppy (through membership of
|
||||
# the floppy group)
|
||||
#
|
||||
|
||||
#xsh;tty*&!ttyp*;us;Al0000-2400;floppy
|
||||
|
||||
#
|
||||
# another example: running 'xsh' on tty* (any ttyXXX device),
|
||||
# the user 'sword' is given access to games (through membership of
|
||||
# the floppy group) after work hours
|
||||
#
|
||||
|
||||
#xsh; tty* ;sword;!Wk0900-1800;games, sound
|
||||
#xsh; tty* ;*;Al0900-1800;floppy
|
||||
|
||||
#
|
||||
# End of group.conf file
|
||||
#
|
@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFILE=$FAKEROOT"$CONFILE"
|
||||
IGNORE_AGE=./.ignore_age
|
||||
QUIET_INSTALL=../../.quiet_install
|
||||
CONF=./group.conf
|
||||
MODULE=pam_group
|
||||
|
||||
echo
|
||||
|
||||
if [ -f "$QUIET_INSTALL" ]; then
|
||||
if [ ! -f "$CONFILE" ]; then
|
||||
yes="y"
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
elif [ -f "$IGNORE_AGE" ]; then
|
||||
echo "you don't want to be bothered with the age of your $CONFILE file"
|
||||
yes="n"
|
||||
elif [ ! -f "$CONFILE" ] || [ "$CONF" -nt "$CONFILE" ]; then
|
||||
if [ -f "$CONFILE" ]; then
|
||||
echo "An older $MODULE configuration file already exists ($CONFILE)"
|
||||
echo "Do you wish to copy the $CONF file in this distribution"
|
||||
echo "to $CONFILE ? (y/n) [skip] "
|
||||
read yes
|
||||
else
|
||||
yes="y"
|
||||
fi
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
|
||||
if [ "$yes" = "y" ]; then
|
||||
mkdir -p $FAKEROOT$CONFD
|
||||
echo " copying $CONF to $CONFILE"
|
||||
cp $CONF $CONFILE
|
||||
else
|
||||
echo " Skipping $CONF installation"
|
||||
if [ "$yes" = "n" ]; then
|
||||
touch "$IGNORE_AGE"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
@ -1,862 +0,0 @@
|
||||
/* pam_group module */
|
||||
|
||||
/*
|
||||
* $Id: pam_group.c,v 1.7 1997/02/15 17:31:48 morgan Exp morgan $
|
||||
*
|
||||
* Written by Andrew Morgan <morgan@parc.power.net> 1996/7/6
|
||||
*
|
||||
* $Log: pam_group.c,v $
|
||||
* Revision 1.7 1997/02/15 17:31:48 morgan
|
||||
* time parsing more robust
|
||||
*
|
||||
* Revision 1.6 1997/01/04 21:57:49 morgan
|
||||
* fixed warning about setgroups not being defined
|
||||
*
|
||||
* Revision 1.5 1997/01/04 20:26:49 morgan
|
||||
* can be compiled with and without libpwdb. fixed buffer underwriting
|
||||
* pays attention to PAM_CRED flags(!)
|
||||
*
|
||||
* Revision 1.4 1996/12/01 02:54:37 morgan
|
||||
* mostly debugging now uses D(())
|
||||
*
|
||||
* Revision 1.3 1996/11/10 21:01:22 morgan
|
||||
* compatability and pam_get_user changes
|
||||
*/
|
||||
|
||||
const static char rcsid[] =
|
||||
"$Id: pam_group.c,v 1.7 1997/02/15 17:31:48 morgan Exp morgan $;\n"
|
||||
"Version 0.5 for Linux-PAM\n"
|
||||
"Copyright (c) Andrew G. Morgan 1996 <morgan@parc.power.net>\n";
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
|
||||
#define __USE_BSD
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef WANT_PWDB
|
||||
#include <pwdb/pwdb_public.h>
|
||||
#endif
|
||||
|
||||
#define PAM_GROUP_CONF CONFILE /* from external define */
|
||||
#define PAM_GROUP_BUFLEN 1000
|
||||
#define FIELD_SEPARATOR ';' /* this is new as of .02 */
|
||||
|
||||
typedef enum { FALSE, TRUE } boolean;
|
||||
typedef enum { AND, OR } operator;
|
||||
|
||||
/*
|
||||
* here, we make definitions for the externally accessible functions
|
||||
* in this file (these definitions are required for static modules
|
||||
* but strongly encouraged generally) they are used to instruct the
|
||||
* modules include file to define their prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
/* --- static functions for checking whether the user should be let in --- */
|
||||
|
||||
static void _log_err(const char *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("pam_group", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(LOG_CRIT, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
static void shift_bytes(char *mem, int from, int by)
|
||||
{
|
||||
while (by-- > 0) {
|
||||
*mem = mem[from];
|
||||
++mem;
|
||||
}
|
||||
}
|
||||
|
||||
static int read_field(int fd, char **buf, int *from, int *to)
|
||||
{
|
||||
/* is buf set ? */
|
||||
|
||||
if (! *buf) {
|
||||
*buf = (char *) malloc(PAM_GROUP_BUFLEN);
|
||||
if (! *buf) {
|
||||
_log_err("out of memory");
|
||||
return -1;
|
||||
}
|
||||
*from = *to = 0;
|
||||
fd = open(PAM_GROUP_CONF, O_RDONLY);
|
||||
}
|
||||
|
||||
/* do we have a file open ? return error */
|
||||
|
||||
if (fd < 0 && *to <= 0) {
|
||||
_log_err( PAM_GROUP_CONF " not opened");
|
||||
memset(*buf, 0, PAM_GROUP_BUFLEN);
|
||||
_pam_drop(*buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* check if there was a newline last time */
|
||||
|
||||
if ((*to > *from) && (*to > 0)
|
||||
&& ((*buf)[*from] == '\0')) { /* previous line ended */
|
||||
(*from)++;
|
||||
(*buf)[0] = '\0';
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* ready for more data: first shift the buffer's remaining data */
|
||||
|
||||
*to -= *from;
|
||||
shift_bytes(*buf, *from, *to);
|
||||
*from = 0;
|
||||
(*buf)[*to] = '\0';
|
||||
|
||||
while (fd >= 0 && *to < PAM_GROUP_BUFLEN) {
|
||||
int i;
|
||||
|
||||
/* now try to fill the remainder of the buffer */
|
||||
|
||||
i = read(fd, *to + *buf, PAM_GROUP_BUFLEN - *to);
|
||||
if (i < 0) {
|
||||
_log_err("error reading " PAM_GROUP_CONF);
|
||||
return -1;
|
||||
} else if (!i) {
|
||||
fd = -1; /* end of file reached */
|
||||
} else
|
||||
*to += i;
|
||||
|
||||
/*
|
||||
* contract the buffer. Delete any comments, and replace all
|
||||
* multiple spaces with single commas
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
#ifdef DEBUG_DUMP
|
||||
D(("buffer=<%s>",*buf));
|
||||
#endif
|
||||
while (i < *to) {
|
||||
if ((*buf)[i] == ',') {
|
||||
int j;
|
||||
|
||||
for (j=++i; j<*to && (*buf)[j] == ','; ++j);
|
||||
if (j!=i) {
|
||||
shift_bytes(i + (*buf), j-i, (*to) - j);
|
||||
*to -= j-i;
|
||||
}
|
||||
}
|
||||
switch ((*buf)[i]) {
|
||||
int j,c;
|
||||
case '#':
|
||||
for (j=i; j < *to && (c = (*buf)[j]) != '\n'; ++j);
|
||||
if (j >= *to) {
|
||||
(*buf)[*to = ++i] = '\0';
|
||||
} else if (c == '\n') {
|
||||
shift_bytes(i + (*buf), j-i, (*to) - j);
|
||||
*to -= j-i;
|
||||
++i;
|
||||
} else {
|
||||
_log_err("internal error in " __FILE__
|
||||
" at line %d", __LINE__ );
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
if ((*buf)[i+1] == '\n') {
|
||||
shift_bytes(i + *buf, 2, *to - (i+2));
|
||||
*to -= 2;
|
||||
}
|
||||
break;
|
||||
case '!':
|
||||
case ' ':
|
||||
case '\t':
|
||||
if ((*buf)[i] != '!')
|
||||
(*buf)[i] = ',';
|
||||
/* delete any trailing spaces */
|
||||
for (j=++i; j < *to && ( (c = (*buf)[j]) == ' '
|
||||
|| c == '\t' ); ++j);
|
||||
shift_bytes(i + *buf, j-i, (*to)-j );
|
||||
*to -= j-i;
|
||||
break;
|
||||
default:
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(*buf)[*to] = '\0';
|
||||
|
||||
/* now return the next field (set the from/to markers) */
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i=0; i<*to; ++i) {
|
||||
switch ((*buf)[i]) {
|
||||
case '#':
|
||||
case '\n': /* end of the line/file */
|
||||
(*buf)[i] = '\0';
|
||||
*from = i;
|
||||
return fd;
|
||||
case FIELD_SEPARATOR: /* end of the field */
|
||||
(*buf)[i] = '\0';
|
||||
*from = ++i;
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
*from = i;
|
||||
(*buf)[*from] = '\0';
|
||||
}
|
||||
|
||||
if (*to <= 0) {
|
||||
D(("[end of text]"));
|
||||
*buf = NULL;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* read a member from a field */
|
||||
|
||||
static int logic_member(const char *string, int *at)
|
||||
{
|
||||
int len,c,to;
|
||||
int done=0;
|
||||
int token=0;
|
||||
|
||||
len=0;
|
||||
to=*at;
|
||||
do {
|
||||
c = string[to++];
|
||||
|
||||
switch (c) {
|
||||
|
||||
case '\0':
|
||||
--to;
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
case '|':
|
||||
case '!':
|
||||
if (token) {
|
||||
--to;
|
||||
}
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isalpha(c) || c == '*' || isdigit(c) || c == '_'
|
||||
|| c == '-' || c == '.') {
|
||||
token = 1;
|
||||
} else if (token) {
|
||||
--to;
|
||||
done = 1;
|
||||
} else {
|
||||
++*at;
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
return to - *at;
|
||||
}
|
||||
|
||||
typedef enum { VAL, OP } expect;
|
||||
|
||||
static boolean logic_field(const void *me, const char *x, int rule,
|
||||
boolean (*agrees)(const void *, const char *
|
||||
, int, int))
|
||||
{
|
||||
boolean left=FALSE, right, not=FALSE;
|
||||
operator oper=OR;
|
||||
int at=0, l;
|
||||
expect next=VAL;
|
||||
|
||||
while ((l = logic_member(x,&at))) {
|
||||
int c = x[at];
|
||||
|
||||
if (next == VAL) {
|
||||
if (c == '!')
|
||||
not = !not;
|
||||
else if (isalpha(c) || c == '*') {
|
||||
right = not ^ agrees(me, x+at, l, rule);
|
||||
if (oper == AND)
|
||||
left &= right;
|
||||
else
|
||||
left |= right;
|
||||
next = OP;
|
||||
} else {
|
||||
_log_err("garbled syntax; expected name (rule #%d)", rule);
|
||||
return FALSE;
|
||||
}
|
||||
} else { /* OP */
|
||||
switch (c) {
|
||||
case '&':
|
||||
oper = AND;
|
||||
break;
|
||||
case '|':
|
||||
oper = OR;
|
||||
break;
|
||||
default:
|
||||
_log_err("garbled syntax; expected & or | (rule #%d)"
|
||||
, rule);
|
||||
D(("%c at %d",c,at));
|
||||
return FALSE;
|
||||
}
|
||||
next = VAL;
|
||||
}
|
||||
at += l;
|
||||
}
|
||||
|
||||
return left;
|
||||
}
|
||||
|
||||
static boolean is_same(const void *A, const char *b, int len, int rule)
|
||||
{
|
||||
int i;
|
||||
const char *a;
|
||||
|
||||
a = A;
|
||||
for (i=0; len > 0; ++i, --len) {
|
||||
if (b[i] != a[i]) {
|
||||
if (b[i++] == '*') {
|
||||
return (!--len || !strncmp(b+i,a+strlen(a)-len,len));
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return ( !len );
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int day; /* array of 7 bits, one set for today */
|
||||
int minute; /* integer, hour*100+minute for now */
|
||||
} TIME;
|
||||
|
||||
struct day {
|
||||
const char *d;
|
||||
int bit;
|
||||
} static const days[11] = {
|
||||
{ "su", 01 },
|
||||
{ "mo", 02 },
|
||||
{ "tu", 04 },
|
||||
{ "we", 010 },
|
||||
{ "th", 020 },
|
||||
{ "fr", 040 },
|
||||
{ "sa", 0100 },
|
||||
{ "wk", 076 },
|
||||
{ "wd", 0101 },
|
||||
{ "al", 0177 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static TIME time_now(void)
|
||||
{
|
||||
struct tm *local;
|
||||
time_t the_time;
|
||||
TIME this;
|
||||
|
||||
the_time = time((time_t *)0); /* get the current time */
|
||||
local = localtime(&the_time);
|
||||
this.day = days[local->tm_wday].bit;
|
||||
this.minute = local->tm_hour*100 + local->tm_min;
|
||||
|
||||
D(("day: 0%o, time: %.4d", this.day, this.minute));
|
||||
return this;
|
||||
}
|
||||
|
||||
/* take the current date and see if the range "date" passes it */
|
||||
static boolean check_time(const void *AT, const char *times, int len, int rule)
|
||||
{
|
||||
boolean not,pass;
|
||||
int marked_day, time_start, time_end;
|
||||
const TIME *at;
|
||||
int i,j=0;
|
||||
|
||||
at = AT;
|
||||
D(("checking: 0%o/%.4d vs. %s", at->day, at->minute, times));
|
||||
|
||||
if (times == NULL) {
|
||||
/* this should not happen */
|
||||
_log_err("internal error: " __FILE__ " line %d", __LINE__);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (times[j] == '!') {
|
||||
++j;
|
||||
not = TRUE;
|
||||
} else {
|
||||
not = FALSE;
|
||||
}
|
||||
|
||||
for (marked_day = 0; len > 0 && isalpha(times[j]); --len) {
|
||||
int this_day=-1;
|
||||
|
||||
D(("%c%c ?", times[j], times[j+1]));
|
||||
for (i=0; days[i].d != NULL; ++i) {
|
||||
if (tolower(times[j]) == days[i].d[0]
|
||||
&& tolower(times[j+1]) == days[i].d[1] ) {
|
||||
this_day = days[i].bit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
j += 2;
|
||||
if (this_day == -1) {
|
||||
_log_err("bad day specified (rule #%d)", rule);
|
||||
return FALSE;
|
||||
}
|
||||
marked_day ^= this_day;
|
||||
}
|
||||
if (marked_day == 0) {
|
||||
_log_err("no day specified");
|
||||
return FALSE;
|
||||
}
|
||||
D(("day range = 0%o", marked_day));
|
||||
|
||||
time_start = 0;
|
||||
for (i=0; len > 0 && i < 4 && isdigit(times[i+j]); ++i, --len) {
|
||||
time_start *= 10;
|
||||
time_start += times[i+j]-'0'; /* is this portable? */
|
||||
}
|
||||
j += i;
|
||||
|
||||
if (times[j] == '-') {
|
||||
time_end = 0;
|
||||
for (i=1; len > 0 && i < 5 && isdigit(times[i+j]); ++i, --len) {
|
||||
time_end *= 10;
|
||||
time_end += times[i+j]-'0'; /* is this portable? */
|
||||
}
|
||||
j += i;
|
||||
} else
|
||||
time_end = -1;
|
||||
|
||||
D(("i=%d, time_end=%d, times[j]='%c'", i, time_end, times[j]));
|
||||
if (i != 5 || time_end == -1) {
|
||||
_log_err("no/bad times specified (rule #%d)", rule);
|
||||
return TRUE;
|
||||
}
|
||||
D(("times(%d to %d)", time_start,time_end));
|
||||
D(("marked_day = 0%o", marked_day));
|
||||
|
||||
/* compare with the actual time now */
|
||||
|
||||
pass = FALSE;
|
||||
if (time_start < time_end) { /* start < end ? --> same day */
|
||||
if ((at->day & marked_day) && (at->minute >= time_start)
|
||||
&& (at->minute < time_end)) {
|
||||
D(("time is listed"));
|
||||
pass = TRUE;
|
||||
}
|
||||
} else { /* spans two days */
|
||||
if ((at->day & marked_day) && (at->minute >= time_start)) {
|
||||
D(("caught on first day"));
|
||||
pass = TRUE;
|
||||
} else {
|
||||
marked_day <<= 1;
|
||||
marked_day |= (marked_day & 0200) ? 1:0;
|
||||
D(("next day = 0%o", marked_day));
|
||||
if ((at->day & marked_day) && (at->minute <= time_end)) {
|
||||
D(("caught on second day"));
|
||||
pass = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (not ^ pass);
|
||||
}
|
||||
|
||||
static int find_member(const char *string, int *at)
|
||||
{
|
||||
int len,c,to;
|
||||
int done=0;
|
||||
int token=0;
|
||||
|
||||
len=0;
|
||||
to=*at;
|
||||
do {
|
||||
c = string[to++];
|
||||
|
||||
switch (c) {
|
||||
|
||||
case '\0':
|
||||
--to;
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
case '|':
|
||||
case '!':
|
||||
if (token) {
|
||||
--to;
|
||||
}
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isalpha(c) || isdigit(c) || c == '_' || c == '*'
|
||||
|| c == '-') {
|
||||
token = 1;
|
||||
} else if (token) {
|
||||
--to;
|
||||
done = 1;
|
||||
} else {
|
||||
++*at;
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
|
||||
return to - *at;
|
||||
}
|
||||
|
||||
#define GROUP_BLK 10
|
||||
#define blk_size(len) (((len-1 + GROUP_BLK)/GROUP_BLK)*GROUP_BLK)
|
||||
|
||||
static int mkgrplist(char *buf, gid_t **list, int len)
|
||||
{
|
||||
int l,at=0;
|
||||
int blks;
|
||||
|
||||
blks = blk_size(len);
|
||||
D(("cf. blks=%d and len=%d", blks,len));
|
||||
|
||||
while ((l = find_member(buf,&at))) {
|
||||
int edge;
|
||||
|
||||
if (len >= blks) {
|
||||
gid_t *tmp;
|
||||
|
||||
D(("allocating new block"));
|
||||
tmp = (gid_t *) realloc((*list)
|
||||
, sizeof(gid_t) * (blks += GROUP_BLK));
|
||||
if (tmp != NULL) {
|
||||
(*list) = tmp;
|
||||
} else {
|
||||
_log_err("out of memory for group list");
|
||||
free(*list);
|
||||
(*list) = NULL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* '\0' terminate the entry */
|
||||
|
||||
edge = (buf[at+l]) ? 1:0;
|
||||
buf[at+l] = '\0';
|
||||
D(("found group: %s",buf+at));
|
||||
|
||||
/* this is where we convert a group name to a gid_t */
|
||||
#ifdef WANT_PWDB
|
||||
{
|
||||
int retval;
|
||||
const struct pwdb *pw=NULL;
|
||||
|
||||
retval = pwdb_locate("group", PWDB_DEFAULT, buf+at
|
||||
, PWDB_ID_UNKNOWN, &pw);
|
||||
if (retval != PWDB_SUCCESS) {
|
||||
_log_err("bad group: %s; %s", buf+at, pwdb_strerror(retval));
|
||||
} else {
|
||||
const struct pwdb_entry *pwe=NULL;
|
||||
|
||||
D(("group %s exists", buf+at));
|
||||
retval = pwdb_get_entry(pw, "gid", &pwe);
|
||||
if (retval == PWDB_SUCCESS) {
|
||||
D(("gid = %d [%p]",* (const gid_t *) pwe->value,list));
|
||||
(*list)[len++] = * (const gid_t *) pwe->value;
|
||||
pwdb_entry_delete(&pwe); /* tidy up */
|
||||
} else {
|
||||
_log_err("%s group entry is bad; %s"
|
||||
, pwdb_strerror(retval));
|
||||
}
|
||||
pw = NULL; /* break link - cached for later use */
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
const struct group *grp;
|
||||
|
||||
grp = getgrnam(buf+at);
|
||||
if (grp == NULL) {
|
||||
_log_err("bad group: %s", buf+at);
|
||||
} else {
|
||||
D(("group %s exists", buf+at));
|
||||
(*list)[len++] = grp->gr_gid;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* next entry along */
|
||||
|
||||
at += l + edge;
|
||||
}
|
||||
D(("returning with [%p/len=%d]->%p",list,len,*list));
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static int check_account(const char *service, const char *tty
|
||||
, const char *user)
|
||||
{
|
||||
int from=0,to=0,fd=-1;
|
||||
char *buffer=NULL;
|
||||
int count=0;
|
||||
TIME here_and_now;
|
||||
int retval=PAM_SUCCESS;
|
||||
gid_t *grps;
|
||||
int no_grps;
|
||||
|
||||
/*
|
||||
* first we get the current list of groups - the application
|
||||
* will have previously done an initgroups(), or equivalent.
|
||||
*/
|
||||
|
||||
D(("counting supplementary groups"));
|
||||
no_grps = getgroups(0, NULL); /* find the current number of groups */
|
||||
if (no_grps > 0) {
|
||||
grps = calloc( blk_size(no_grps) , sizeof(gid_t) );
|
||||
D(("copying current list into grps [%d big]",blk_size(no_grps)));
|
||||
(void) getgroups(no_grps, grps);
|
||||
#ifdef DEBUG
|
||||
{
|
||||
int z;
|
||||
for (z=0; z<no_grps; ++z) {
|
||||
D(("gid[%d]=%d", z, grps[z]));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
D(("no supplementary groups known"));
|
||||
no_grps = 0;
|
||||
grps = NULL;
|
||||
}
|
||||
|
||||
here_and_now = time_now(); /* find current time */
|
||||
|
||||
/* parse the rules in the configuration file */
|
||||
do {
|
||||
int good=TRUE;
|
||||
|
||||
/* here we get the service name field */
|
||||
|
||||
fd = read_field(fd,&buffer,&from,&to);
|
||||
if (!buffer || !buffer[0]) {
|
||||
/* empty line .. ? */
|
||||
continue;
|
||||
}
|
||||
++count;
|
||||
D(("working on rule #%d",count));
|
||||
|
||||
good = logic_field(service, buffer, count, is_same);
|
||||
D(("with service: %s", good ? "passes":"fails" ));
|
||||
|
||||
/* here we get the terminal name field */
|
||||
|
||||
fd = read_field(fd,&buffer,&from,&to);
|
||||
if (!buffer || !buffer[0]) {
|
||||
_log_err(PAM_GROUP_CONF "; no tty entry #%d", count);
|
||||
continue;
|
||||
}
|
||||
good &= logic_field(tty, buffer, count, is_same);
|
||||
D(("with tty: %s", good ? "passes":"fails" ));
|
||||
|
||||
/* here we get the username field */
|
||||
|
||||
fd = read_field(fd,&buffer,&from,&to);
|
||||
if (!buffer || !buffer[0]) {
|
||||
_log_err(PAM_GROUP_CONF "; no user entry #%d", count);
|
||||
continue;
|
||||
}
|
||||
good &= logic_field(user, buffer, count, is_same);
|
||||
D(("with user: %s", good ? "passes":"fails" ));
|
||||
|
||||
/* here we get the time field */
|
||||
|
||||
fd = read_field(fd,&buffer,&from,&to);
|
||||
if (!buffer || !buffer[0]) {
|
||||
_log_err(PAM_GROUP_CONF "; no time entry #%d", count);
|
||||
continue;
|
||||
}
|
||||
|
||||
good &= logic_field(&here_and_now, buffer, count, check_time);
|
||||
D(("with time: %s", good ? "passes":"fails" ));
|
||||
|
||||
fd = read_field(fd,&buffer,&from,&to);
|
||||
if (!buffer || !buffer[0]) {
|
||||
_log_err(PAM_GROUP_CONF "; no listed groups for rule #%d"
|
||||
, count);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* so we have a list of groups, we need to turn it into
|
||||
* something to send to setgroups(2)
|
||||
*/
|
||||
|
||||
if (good) {
|
||||
D(("adding %s to gid list", buffer));
|
||||
good = mkgrplist(buffer, &grps, no_grps);
|
||||
if (good < 0) {
|
||||
no_grps = 0;
|
||||
} else {
|
||||
no_grps = good;
|
||||
}
|
||||
}
|
||||
|
||||
/* check the line is terminated correctly */
|
||||
|
||||
fd = read_field(fd,&buffer,&from,&to);
|
||||
if (buffer && buffer[0]) {
|
||||
_log_err(PAM_GROUP_CONF "; poorly terminated rule #%d", count);
|
||||
}
|
||||
|
||||
if (good > 0) {
|
||||
D(("rule #%d passed, added %d groups", count, good));
|
||||
} else if (good < 0) {
|
||||
retval = PAM_BUF_ERR;
|
||||
} else {
|
||||
D(("rule #%d failed", count));
|
||||
}
|
||||
|
||||
} while (buffer);
|
||||
|
||||
/* now set the groups for the user */
|
||||
|
||||
if (no_grps > 0) {
|
||||
int err;
|
||||
D(("trying to set %d groups", no_grps));
|
||||
#ifdef DEBUG
|
||||
for (err=0; err<no_grps; ++err) {
|
||||
D(("gid[%d]=%d", err, grps[err]));
|
||||
}
|
||||
#endif
|
||||
if ((err = setgroups(no_grps, grps))) {
|
||||
D(("but couldn't set groups %d", err));
|
||||
_log_err("unable to set the group membership for user (err=%d)"
|
||||
, err);
|
||||
retval = PAM_CRED_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (grps) { /* tidy up */
|
||||
memset(grps, 0, sizeof(gid_t) * blk_size(no_grps));
|
||||
_pam_drop(grps);
|
||||
no_grps = 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* --- public authentication management functions --- */
|
||||
|
||||
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags
|
||||
, int argc, const char **argv)
|
||||
{
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
|
||||
, int argc, const char **argv)
|
||||
{
|
||||
const char *service=NULL, *tty=NULL;
|
||||
const char *user=NULL;
|
||||
int retval;
|
||||
unsigned setting;
|
||||
|
||||
/* only interested in establishing credentials */
|
||||
|
||||
setting = flags;
|
||||
if (!(setting & PAM_ESTABLISH_CRED)) {
|
||||
D(("ignoring call - not for establishing credentials"));
|
||||
return PAM_SUCCESS; /* don't fail because of this */
|
||||
}
|
||||
|
||||
/* set service name */
|
||||
|
||||
if (pam_get_item(pamh, PAM_SERVICE, (const void **)&service)
|
||||
!= PAM_SUCCESS || service == NULL) {
|
||||
_log_err("cannot find the current service name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
|
||||
/* set username */
|
||||
|
||||
if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL
|
||||
|| *user == '\0') {
|
||||
_log_err("cannot determine the user's name");
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
/* set tty name */
|
||||
|
||||
if (pam_get_item(pamh, PAM_TTY, (const void **)&tty) != PAM_SUCCESS
|
||||
|| tty == NULL) {
|
||||
D(("PAM_TTY not set, probing stdin"));
|
||||
tty = ttyname(STDIN_FILENO);
|
||||
if (tty == NULL) {
|
||||
_log_err("couldn't get the tty name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
if (pam_set_item(pamh, PAM_TTY, tty) != PAM_SUCCESS) {
|
||||
_log_err("couldn't set tty name");
|
||||
return PAM_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (strncmp("/dev/",tty,5) == 0) { /* strip leading /dev/ */
|
||||
tty += 5;
|
||||
}
|
||||
|
||||
/* good, now we have the service name, the user and the terminal name */
|
||||
|
||||
D(("service=%s", service));
|
||||
D(("user=%s", user));
|
||||
D(("tty=%s", tty));
|
||||
|
||||
#ifdef WANT_PWDB
|
||||
|
||||
/* We initialize the pwdb library and check the account */
|
||||
retval = pwdb_start(); /* initialize */
|
||||
if (retval == PWDB_SUCCESS) {
|
||||
retval = check_account(service,tty,user); /* get groups */
|
||||
(void) pwdb_end(); /* tidy up */
|
||||
} else {
|
||||
D(("failed to initialize pwdb; %s", pwdb_strerror(retval)));
|
||||
_log_err("unable to initialize libpwdb");
|
||||
retval = PAM_ABORT;
|
||||
}
|
||||
|
||||
#else /* WANT_PWDB */
|
||||
retval = check_account(service,tty,user); /* get groups */
|
||||
#endif /* WANT_PWDB */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* end of module definition */
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_group_modstruct = {
|
||||
"pam_group",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#endif
|
@ -1,106 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.2 1997/04/05 06:17:14 morgan Exp morgan $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.2 1997/04/05 06:17:14 morgan
|
||||
# fakeroot fixed
|
||||
#
|
||||
# Revision 1.1 1997/01/04 20:29:28 morgan
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/12/8
|
||||
#
|
||||
|
||||
# Convenient defaults for compiling independently of the full source
|
||||
# tree.
|
||||
ifndef FULL_LINUX_PAM_SOURCE_TREE
|
||||
export DYNAMIC=-DPAM_DYNAMIC
|
||||
export CC=gcc
|
||||
export CFLAGS=-O2 -Dlinux -DLINUX_PAM \
|
||||
-ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \
|
||||
-Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \
|
||||
-Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \
|
||||
-Wshadow -pedantic -fPIC
|
||||
export MKDIR=mkdir -p
|
||||
export LD_D=gcc -shared -Xlinker -x
|
||||
endif
|
||||
|
||||
TITLE=pam_lastlog
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak dynamic/* static/*
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,469 +0,0 @@
|
||||
/* pam_lastlog module */
|
||||
|
||||
/*
|
||||
* $Id: pam_lastlog.c,v 1.3 1997/04/05 06:18:21 morgan Exp morgan $
|
||||
*
|
||||
* Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11
|
||||
*
|
||||
* This module does the necessary work to display the last login
|
||||
* time+date for this user, it then updates this entry for the
|
||||
* present (login) service.
|
||||
*
|
||||
* $Log: pam_lastlog.c,v $
|
||||
* Revision 1.3 1997/04/05 06:18:21 morgan
|
||||
* removed xstrdup - unused
|
||||
*
|
||||
* Revision 1.2 1997/02/15 17:18:21 morgan
|
||||
* removed fixed buffer in logging
|
||||
*
|
||||
* Revision 1.1 1997/01/04 20:29:28 morgan
|
||||
* Initial revision
|
||||
*
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#ifdef HAVE_UTMP_H
|
||||
# include <utmp.h>
|
||||
#else
|
||||
# include <lastlog.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef WANT_PWDB
|
||||
#include <pwdb/pwdb_public.h> /* use POSIX front end */
|
||||
#endif
|
||||
|
||||
#if defined(hpux) || defined(sunos) || defined(solaris)
|
||||
# ifndef _PATH_LASTLOG
|
||||
# define _PATH_LASTLOG "/usr/adm/lastlog"
|
||||
# endif /* _PATH_LASTLOG */
|
||||
# ifndef UT_HOSTSIZE
|
||||
# define UT_HOSTSIZE 16
|
||||
# endif /* UT_HOSTSIZE */
|
||||
# ifndef UT_LINESIZE
|
||||
# define UT_LINESIZE 12
|
||||
# endif /* UT_LINESIZE */
|
||||
#endif
|
||||
#if defined(hpux)
|
||||
struct lastlog {
|
||||
time_t ll_time;
|
||||
char ll_line[UT_LINESIZE];
|
||||
char ll_host[UT_HOSTSIZE]; /* same as in utmp */
|
||||
};
|
||||
#endif /* hpux */
|
||||
|
||||
/* XXX - time before ignoring lock. Is 1 sec enough? */
|
||||
#define LASTLOG_IGNORE_LOCK_TIME 1
|
||||
|
||||
#define DEFAULT_HOST "" /* "[no.where]" */
|
||||
#define DEFAULT_TERM "" /* "tt???" */
|
||||
#define LASTLOG_NEVER_WELCOME "Welcome to your new account!"
|
||||
#define LASTLOG_INTRO "Last login:"
|
||||
#define LASTLOG_TIME " %s"
|
||||
#define _LASTLOG_HOST_FORMAT " from %%.%ds"
|
||||
#define _LASTLOG_LINE_FORMAT " on %%.%ds"
|
||||
#define LASTLOG_TAIL ""
|
||||
#define LASTLOG_MAXSIZE (sizeof(LASTLOG_INTRO)+0 \
|
||||
+sizeof(LASTLOG_TIME)+strlen(the_time) \
|
||||
+sizeof(_LASTLOG_HOST_FORMAT)+UT_HOSTSIZE \
|
||||
+sizeof(_LASTLOG_LINE_FORMAT)+UT_LINESIZE \
|
||||
+sizeof(LASTLOG_TAIL))
|
||||
|
||||
/*
|
||||
* here, we make a definition for the externally accessible function
|
||||
* in this file (this definition is required for static a module
|
||||
* but strongly encouraged generally) it is used to instruct the
|
||||
* modules include file to define the function prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_SESSION
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
/* some syslogging */
|
||||
|
||||
static void _log_err(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("PAM-lastlog", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
/* argument parsing */
|
||||
|
||||
#define LASTLOG_DATE 01 /* display the date of the last login */
|
||||
#define LASTLOG_HOST 02 /* display the last host used (if set) */
|
||||
#define LASTLOG_LINE 04 /* display the last terminal used */
|
||||
#define LASTLOG_NEVER 010 /* display a welcome message for first login */
|
||||
#define LASTLOG_DEBUG 020 /* send info to syslog(3) */
|
||||
#define LASTLOG_QUIET 040 /* keep quiet about things */
|
||||
|
||||
static int _pam_parse(int flags, int argc, const char **argv)
|
||||
{
|
||||
int ctrl=(LASTLOG_DATE|LASTLOG_HOST|LASTLOG_LINE);
|
||||
|
||||
/* does the appliction require quiet? */
|
||||
if (flags & PAM_SILENT) {
|
||||
ctrl |= LASTLOG_QUIET;
|
||||
}
|
||||
|
||||
/* step through arguments */
|
||||
for (; argc-- > 0; ++argv) {
|
||||
|
||||
/* generic options */
|
||||
|
||||
if (!strcmp(*argv,"debug")) {
|
||||
ctrl |= LASTLOG_DEBUG;
|
||||
} else if (!strcmp(*argv,"nodate")) {
|
||||
ctrl |= ~LASTLOG_DATE;
|
||||
} else if (!strcmp(*argv,"noterm")) {
|
||||
ctrl |= ~LASTLOG_LINE;
|
||||
} else if (!strcmp(*argv,"nohost")) {
|
||||
ctrl |= ~LASTLOG_HOST;
|
||||
} else if (!strcmp(*argv,"silent")) {
|
||||
ctrl |= LASTLOG_QUIET;
|
||||
} else if (!strcmp(*argv,"never")) {
|
||||
ctrl |= LASTLOG_NEVER;
|
||||
} else {
|
||||
_log_err(LOG_ERR,"unknown option; %s",*argv);
|
||||
}
|
||||
}
|
||||
|
||||
D(("ctrl = %o", ctrl));
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
/* a front end for conversations */
|
||||
|
||||
static int converse(pam_handle_t *pamh, int ctrl, int nargs
|
||||
, struct pam_message **message
|
||||
, struct pam_response **response)
|
||||
{
|
||||
int retval;
|
||||
struct pam_conv *conv;
|
||||
|
||||
D(("begin to converse"));
|
||||
|
||||
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
|
||||
if ( retval == PAM_SUCCESS ) {
|
||||
|
||||
retval = conv->conv(nargs, ( const struct pam_message ** ) message
|
||||
, response, conv->appdata_ptr);
|
||||
|
||||
D(("returned from application's conversation function"));
|
||||
|
||||
if (retval != PAM_SUCCESS && (ctrl & LASTLOG_DEBUG) ) {
|
||||
_log_err(LOG_DEBUG, "conversation failure [%s]"
|
||||
, pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
} else {
|
||||
_log_err(LOG_ERR, "couldn't obtain coversation function [%s]"
|
||||
, pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
D(("ready to return from module conversation"));
|
||||
|
||||
return retval; /* propagate error status */
|
||||
}
|
||||
|
||||
static int make_remark(pam_handle_t *pamh, int ctrl, const char *remark)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!(ctrl & LASTLOG_QUIET)) {
|
||||
struct pam_message msg[1], *mesg[1];
|
||||
struct pam_response *resp=NULL;
|
||||
|
||||
mesg[0] = &msg[0];
|
||||
msg[0].msg_style = PAM_TEXT_INFO;
|
||||
msg[0].msg = remark;
|
||||
|
||||
retval = converse(pamh, ctrl, 1, mesg, &resp);
|
||||
|
||||
msg[0].msg = NULL;
|
||||
if (resp) {
|
||||
_pam_drop_reply(resp, 1);
|
||||
}
|
||||
} else {
|
||||
D(("keeping quiet"));
|
||||
retval = PAM_SUCCESS;
|
||||
}
|
||||
|
||||
D(("returning %s", pam_strerror(pamh, retval)));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Values for the announce flags..
|
||||
*/
|
||||
|
||||
static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid)
|
||||
{
|
||||
struct flock last_lock;
|
||||
struct lastlog last_login;
|
||||
int retval = PAM_SESSION_ERR;
|
||||
int last_fd;
|
||||
|
||||
/* obtain the last login date and all the relevant info */
|
||||
last_fd = open(_PATH_LASTLOG, O_RDWR);
|
||||
if (last_fd < 0) {
|
||||
D(("unable to open the %s file", _PATH_LASTLOG));
|
||||
if (announce & LASTLOG_DEBUG) {
|
||||
_log_err(LOG_DEBUG, "unable to open %s file", _PATH_LASTLOG);
|
||||
}
|
||||
retval = PAM_PERM_DENIED;
|
||||
} else {
|
||||
int win;
|
||||
|
||||
/* read the lastlogin file - for this uid */
|
||||
(void) lseek(last_fd, sizeof(last_login) * (off_t) uid, SEEK_SET);
|
||||
|
||||
memset(&last_lock, 0, sizeof(last_lock));
|
||||
last_lock.l_type = F_RDLCK;
|
||||
last_lock.l_whence = SEEK_SET;
|
||||
last_lock.l_start = sizeof(last_login) * (off_t) uid;
|
||||
last_lock.l_len = sizeof(last_login);
|
||||
|
||||
if ( fcntl(last_fd, F_SETLK, &last_lock) < 0 ) {
|
||||
D(("locking %s failed..(waiting a little)", _PATH_LASTLOG));
|
||||
_log_err(LOG_ALERT, "%s file is locked/read", _PATH_LASTLOG);
|
||||
sleep(LASTLOG_IGNORE_LOCK_TIME);
|
||||
}
|
||||
|
||||
win = ( read(last_fd, &last_login, sizeof(last_login))
|
||||
== sizeof(last_login) );
|
||||
|
||||
last_lock.l_type = F_UNLCK;
|
||||
(void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */
|
||||
|
||||
if (!win) {
|
||||
D(("First login for user uid=%d", _PATH_LASTLOG, uid));
|
||||
if (announce & LASTLOG_DEBUG) {
|
||||
_log_err(LOG_DEBUG, "creating lastlog for uid %d", uid);
|
||||
}
|
||||
memset(&last_login, 0, sizeof(last_login));
|
||||
}
|
||||
|
||||
/* rewind */
|
||||
(void) lseek(last_fd, sizeof(last_login) * (off_t) uid, SEEK_SET);
|
||||
|
||||
if (!(announce & LASTLOG_QUIET)) {
|
||||
if (last_login.ll_time) {
|
||||
char *the_time;
|
||||
char *remark;
|
||||
|
||||
the_time = ctime(&last_login.ll_time);
|
||||
the_time[-1+strlen(the_time)] = '\0'; /* delete '\n' */
|
||||
|
||||
remark = malloc(LASTLOG_MAXSIZE);
|
||||
if (remark == NULL) {
|
||||
D(("no memory for last login remark"));
|
||||
retval = PAM_BUF_ERR;
|
||||
} else {
|
||||
int at;
|
||||
|
||||
/* printing prefix */
|
||||
at = sprintf(remark, "%s", LASTLOG_INTRO);
|
||||
|
||||
/* we want the date? */
|
||||
if (announce & LASTLOG_DATE) {
|
||||
at += sprintf(remark+at, LASTLOG_TIME, the_time);
|
||||
}
|
||||
|
||||
/* we want & have the host? */
|
||||
if ((announce & LASTLOG_HOST)
|
||||
&& (last_login.ll_host[0] != '\0')) {
|
||||
char format[2*sizeof(_LASTLOG_HOST_FORMAT)];
|
||||
|
||||
(void) sprintf(format, _LASTLOG_HOST_FORMAT
|
||||
, UT_HOSTSIZE);
|
||||
D(("format: %s", format));
|
||||
at += sprintf(remark+at, format, last_login.ll_host);
|
||||
_pam_overwrite(format);
|
||||
}
|
||||
|
||||
/* we want and have the terminal? */
|
||||
if ((announce & LASTLOG_LINE)
|
||||
&& (last_login.ll_line[0] != '\0')) {
|
||||
char format[2*sizeof(_LASTLOG_LINE_FORMAT)];
|
||||
|
||||
(void) sprintf(format, _LASTLOG_LINE_FORMAT
|
||||
, UT_LINESIZE);
|
||||
D(("format: %s", format));
|
||||
at += sprintf(remark+at, format, last_login.ll_line);
|
||||
_pam_overwrite(format);
|
||||
}
|
||||
|
||||
/* display requested combo */
|
||||
sprintf(remark+at, "%s", LASTLOG_TAIL);
|
||||
|
||||
retval = make_remark(pamh, announce, remark);
|
||||
|
||||
/* free all the stuff malloced */
|
||||
_pam_overwrite(remark);
|
||||
_pam_drop(remark);
|
||||
}
|
||||
} else if ((!last_login.ll_time) && (announce & LASTLOG_NEVER)) {
|
||||
D(("this is the first time this user has logged in"));
|
||||
retval = make_remark(pamh, announce, LASTLOG_NEVER_WELCOME);
|
||||
}
|
||||
} else {
|
||||
D(("no text was requested"));
|
||||
retval = PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/* write latest value */
|
||||
{
|
||||
const char *remote_host=NULL
|
||||
, *terminal_line=DEFAULT_TERM;
|
||||
|
||||
/* set this login date */
|
||||
D(("set the most recent login time"));
|
||||
|
||||
(void) time(&last_login.ll_time); /* set the time */
|
||||
|
||||
/* set the remote host */
|
||||
(void) pam_get_item(pamh, PAM_RHOST, (const void **)&remote_host);
|
||||
if (remote_host == NULL) {
|
||||
remote_host = DEFAULT_HOST;
|
||||
}
|
||||
|
||||
/* copy to last_login */
|
||||
strncpy(last_login.ll_host, remote_host
|
||||
, sizeof(last_login.ll_host));
|
||||
remote_host = NULL;
|
||||
|
||||
/* set the terminal line */
|
||||
(void) pam_get_item(pamh, PAM_TTY, (const void **)&terminal_line);
|
||||
D(("terminal = %s", terminal_line));
|
||||
if (terminal_line == NULL) {
|
||||
terminal_line = DEFAULT_TERM;
|
||||
} else if ( !strncmp("/dev/", terminal_line, 5) ) {
|
||||
/* strip leading "/dev/" from tty.. */
|
||||
terminal_line += 5;
|
||||
}
|
||||
D(("terminal = %s", terminal_line));
|
||||
|
||||
/* copy to last_login */
|
||||
strncpy(last_login.ll_line, terminal_line
|
||||
, sizeof(last_login.ll_line));
|
||||
terminal_line = NULL;
|
||||
|
||||
D(("locking last_log file"));
|
||||
|
||||
/* now we try to lock this file-record exclusively; non-blocking */
|
||||
memset(&last_lock, 0, sizeof(last_lock));
|
||||
last_lock.l_type = F_WRLCK;
|
||||
last_lock.l_whence = SEEK_SET;
|
||||
last_lock.l_start = sizeof(last_login) * (off_t) uid;
|
||||
last_lock.l_len = sizeof(last_login);
|
||||
|
||||
if ( fcntl(last_fd, F_SETLK, &last_lock) < 0 ) {
|
||||
D(("locking %s failed..(waiting a little)", _PATH_LASTLOG));
|
||||
_log_err(LOG_ALERT, "%s file is locked/write", _PATH_LASTLOG);
|
||||
sleep(LASTLOG_IGNORE_LOCK_TIME);
|
||||
}
|
||||
|
||||
D(("writing to the last_log file"));
|
||||
(void) write(last_fd, &last_login, sizeof(last_login));
|
||||
|
||||
last_lock.l_type = F_UNLCK;
|
||||
(void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */
|
||||
D(("unlocked"));
|
||||
|
||||
close(last_fd); /* all done */
|
||||
}
|
||||
D(("all done with last login"));
|
||||
}
|
||||
|
||||
/* reset the last login structure */
|
||||
memset(&last_login, 0, sizeof(last_login));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* --- authentication management functions (only) --- */
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc
|
||||
, const char **argv)
|
||||
{
|
||||
int retval, ctrl;
|
||||
const char *user;
|
||||
const struct passwd *pwd;
|
||||
uid_t uid;
|
||||
|
||||
/*
|
||||
* this module gets the uid of the PAM_USER. Uses it to display
|
||||
* last login info and then updates the lastlog for that user.
|
||||
*/
|
||||
|
||||
ctrl = _pam_parse(flags, argc, argv);
|
||||
|
||||
/* which user? */
|
||||
|
||||
retval = pam_get_item(pamh, PAM_USER, (const void **)&user);
|
||||
if (retval != PAM_SUCCESS || user == NULL || *user == '\0') {
|
||||
_log_err(LOG_NOTICE, "user unknown");
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
/* what uid? */
|
||||
|
||||
pwd = getpwnam(user);
|
||||
if (pwd == NULL) {
|
||||
D(("couldn't identify user %s", user));
|
||||
return PAM_CRED_INSUFFICIENT;
|
||||
}
|
||||
uid = pwd->pw_uid;
|
||||
pwd = NULL; /* tidy up */
|
||||
|
||||
/* process the current login attempt (indicate last) */
|
||||
|
||||
retval = last_login_date(pamh, ctrl, uid);
|
||||
|
||||
/* indicate success or failure */
|
||||
|
||||
uid = -1; /* forget this */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_lastlog_modstruct = {
|
||||
"pam_lastlog",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
pam_sm_open_session,
|
||||
pam_sm_close_session,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* end of module definition */
|
@ -1,102 +0,0 @@
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# Created by Cristian Gafton <gafton@redhat.com> 1996/09/10
|
||||
#
|
||||
|
||||
ifeq ($(OS),linux)
|
||||
ifeq ($(HAVE_PWDBLIB),yes)
|
||||
TITLE=pam_limits
|
||||
CONFD=$(CONFIGED)/security
|
||||
export CONFD
|
||||
CONFILE=$(CONFD)/limits.conf
|
||||
export CONFILE
|
||||
|
||||
CFLAGS+=-DLIMITS_FILE=\"$(CONFILE)\"
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD) -lpwdb
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
$(MKDIR) $(FAKEROOT)$(SCONFIGED)
|
||||
bash -f ./install_conf
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~ *.so
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak dynamic/* static/*
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
else
|
||||
include ../dont_makefile
|
||||
endif
|
||||
else
|
||||
include ../dont_makefile
|
||||
endif
|
@ -1,87 +0,0 @@
|
||||
|
||||
pam_limits module:
|
||||
Imposing user limits on login.
|
||||
|
||||
THEORY OF OPERATION:
|
||||
|
||||
First, make a root-only-readable file (/etc/limits by default or LIMITS_FILE
|
||||
defined Makefile) that describes the resource limits you wish to impose. No
|
||||
limits are imposed on UID 0 accounts.
|
||||
|
||||
Each line describes a limit for a user in the form:
|
||||
|
||||
<domain> <type> <item> <value>
|
||||
|
||||
Where:
|
||||
<domain> can be:
|
||||
- an user name
|
||||
- a group name, with @group syntax
|
||||
- the wildcard *, for default entry
|
||||
|
||||
<type> can have the two values:
|
||||
- "soft" for enforcinf the soft limits
|
||||
- "hard" for enforcing hard limits
|
||||
|
||||
<item> can be one of the following:
|
||||
- core - limits the core file size (KB)
|
||||
- data - max data size (KB)
|
||||
- fsize - maximum filesize (KB)
|
||||
- memlock - max locked-in-memory address space (KB)
|
||||
- nofile - max number of open files
|
||||
- rss - max resident set size (KB)
|
||||
- stack - max stack size (KB)
|
||||
- cpu - max CPU time (MIN)
|
||||
- nproc - max number of processes
|
||||
- as - address space limit
|
||||
- maxlogins - max number of logins for this user
|
||||
- maxsyslogins - max number of logins on the system
|
||||
|
||||
To completely disable limits for a user (or a group), a single dash (-)
|
||||
will do (Example: 'bin -', '@admin -'). Please remember that individual
|
||||
limits have priority over group limits, so if you impose no limits for admin
|
||||
group, but one of the members in this group have a limits line, the user
|
||||
will have its limits set according to this line.
|
||||
|
||||
Also, please note that all limit settings are set PER LOGIN. They are
|
||||
not global, nor are they permanent (the session only)
|
||||
|
||||
In the LIMITS_FILE, the # character introduces a comment - the rest of the
|
||||
line is ignored.
|
||||
|
||||
The pam_limits module does its best to report configuration problems found
|
||||
in LIMITS_FILE via syslog.
|
||||
|
||||
EXAMPLE configuration file:
|
||||
===========================
|
||||
* soft core 0
|
||||
* hard rss 10000
|
||||
@student hard nproc 20
|
||||
@faculty soft nproc 20
|
||||
@faculty hard nproc 50
|
||||
ftp hard nproc 0
|
||||
@student - maxlogins 4
|
||||
|
||||
|
||||
ARGUMENTS RECOGNIZED:
|
||||
debug verbose logging
|
||||
|
||||
conf=/path/to/file the limits configuration file if different from the
|
||||
one set at compile time.
|
||||
|
||||
MODULE SERVICES PROVIDED:
|
||||
session _open_session and _close_session (blank)
|
||||
|
||||
USAGE:
|
||||
For the services you need resources limits (login for example) put a
|
||||
the following line in /etc/pam.conf as the last line for that
|
||||
service (usually after the pam_unix session line:
|
||||
|
||||
login session required /lib/security/pam_limits.so
|
||||
|
||||
Replace "login" for each service you are using this module, replace
|
||||
"/lib/security" path with your real modules path.
|
||||
|
||||
AUTHOR:
|
||||
Cristian Gafton <gafton@redhat.com>
|
||||
Thanks to Elliot Lee <sopwith@redhat.com> for his comments on
|
||||
improving this module.
|
@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFILE=$FAKEROOT"$CONFILE"
|
||||
IGNORE_AGE=./.ignore_age
|
||||
QUIET_INSTALL=../../.quiet_install
|
||||
CONF=./limits.skel
|
||||
MODULE=pam_limits
|
||||
|
||||
echo
|
||||
|
||||
if [ -f "$QUIET_INSTALL" ]; then
|
||||
if [ ! -f "$CONFILE" ]; then
|
||||
yes="y"
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
elif [ -f "$IGNORE_AGE" ]; then
|
||||
echo "you don't want to be bothered with the age of your $CONFILE file"
|
||||
yes="n"
|
||||
elif [ ! -f "$CONFILE" ] || [ "$CONF" -nt "$CONFILE" ]; then
|
||||
if [ -f "$CONFILE" ]; then
|
||||
echo "An older $MODULE configuration file already exists ($CONFILE)"
|
||||
echo "Do you wish to copy the $CONF file in this distribution"
|
||||
echo "to $CONFILE ? (y/n) [skip] "
|
||||
read yes
|
||||
else
|
||||
yes="y"
|
||||
fi
|
||||
else
|
||||
yes="skip"
|
||||
fi
|
||||
|
||||
if [ "$yes" = "y" ]; then
|
||||
mkdir -p $FAKEROOT$CONFD
|
||||
echo " copying $CONF to $CONFILE"
|
||||
cp $CONF $CONFILE
|
||||
else
|
||||
echo " Skipping $CONF installation"
|
||||
if [ "$yes" = "n" ]; then
|
||||
touch "$IGNORE_AGE"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
exit 0
|
@ -1,41 +0,0 @@
|
||||
# /etc/security/limits.conf
|
||||
#
|
||||
#Each line describes a limit for a user in the form:
|
||||
#
|
||||
#<domain> <type> <item> <value>
|
||||
#
|
||||
#Where:
|
||||
#<domain> can be:
|
||||
# - an user name
|
||||
# - a group name, with @group syntax
|
||||
# - the wildcard *, for default entry
|
||||
#
|
||||
#<type> can have the two values:
|
||||
# - "soft" for enforcing the soft limits
|
||||
# - "hard" for enforcing hard limits
|
||||
#
|
||||
#<item> can be one of the following:
|
||||
# - core - limits the core file size (KB)
|
||||
# - data - max data size (KB)
|
||||
# - fsize - maximum filesize (KB)
|
||||
# - memlock - max locked-in-memory address space (KB)
|
||||
# - nofile - max number of open files
|
||||
# - rss - max resident set size (KB)
|
||||
# - stack - max stack size (KB)
|
||||
# - cpu - max CPU time (MIN)
|
||||
# - nproc - max number of processes
|
||||
# - as - address space limit
|
||||
# - maxlogins - max number of logins for this user
|
||||
#
|
||||
#<domain> <type> <item> <value>
|
||||
#
|
||||
|
||||
#* soft core 0
|
||||
#* hard rss 10000
|
||||
#@student hard nproc 20
|
||||
#@faculty soft nproc 20
|
||||
#@faculty hard nproc 50
|
||||
#ftp hard nproc 0
|
||||
#@student - maxlogins 4
|
||||
|
||||
# End of file
|
@ -1,592 +0,0 @@
|
||||
/*
|
||||
* pam_limits - impose resource limits when opening a user session
|
||||
*
|
||||
* 1.5 - Elliot Lee's "max system logins patch"
|
||||
* 1.4 - addressed bug in configuration file parser
|
||||
* 1.3 - modified the configuration file format
|
||||
* 1.2 - added 'debug' and 'conf=' arguments
|
||||
* 1.1 - added @group support
|
||||
* 1.0 - initial release - Linux ONLY
|
||||
*
|
||||
* See end for Copyright information
|
||||
*/
|
||||
|
||||
#if !(defined(linux))
|
||||
#error THIS CODE IS KNOWN TO WORK ONLY ON LINUX !!!
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#define __USE_POSIX2
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/resource.h>
|
||||
#include <utmp.h>
|
||||
#ifndef UT_USER /* some systems have ut_name instead of ut_user */
|
||||
#define UT_USER ut_user
|
||||
#endif
|
||||
|
||||
/* Module defines */
|
||||
#define LINE_LENGTH 1024
|
||||
|
||||
#define LIMITS_DEF_USER 0 /* limit was set by an user entry */
|
||||
#define LIMITS_DEF_GROUP 1 /* limit was set by a group entry */
|
||||
#define LIMITS_DEF_DEFAULT 2 /* limit was set by an default entry */
|
||||
#define LIMITS_DEF_NONE 3 /* this limit was not set yet */
|
||||
|
||||
/* internal data */
|
||||
static char conf_file[BUFSIZ];
|
||||
|
||||
struct user_limits_struct {
|
||||
int src_soft;
|
||||
int src_hard;
|
||||
struct rlimit limit;
|
||||
};
|
||||
|
||||
static struct user_limits_struct limits[RLIM_NLIMITS];
|
||||
static int login_limit; /* the max logins limit */
|
||||
static int login_limit_def; /* which entry set the login limit */
|
||||
static int flag_numsyslogins; /* whether to limit logins only for a
|
||||
specific user or to count all logins */
|
||||
|
||||
#define LIMIT_LOGIN RLIM_NLIMITS+1
|
||||
#define LIMIT_NUMSYSLOGINS RLIM_NLIMITS+2
|
||||
#define LIMIT_SOFT 1
|
||||
#define LIMIT_HARD 2
|
||||
|
||||
#define PAM_SM_SESSION
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
#include <pwdb/pwdb_map.h>
|
||||
|
||||
/* logging */
|
||||
static void _pam_log(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("pam_limits", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
/* argument parsing */
|
||||
|
||||
#define PAM_DEBUG_ARG 0x0001
|
||||
|
||||
static int _pam_parse(int argc, const char **argv)
|
||||
{
|
||||
int ctrl=0;
|
||||
|
||||
/* step through arguments */
|
||||
for (ctrl=0; argc-- > 0; ++argv) {
|
||||
|
||||
/* generic options */
|
||||
|
||||
if (!strcmp(*argv,"debug"))
|
||||
ctrl |= PAM_DEBUG_ARG;
|
||||
else if (!strncmp(*argv,"conf=",5))
|
||||
strcpy(conf_file,*argv+5);
|
||||
else {
|
||||
_pam_log(LOG_ERR,"pam_parse: unknown option; %s",*argv);
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
/* limits stuff */
|
||||
#ifndef LIMITS_FILE
|
||||
#define LIMITS_FILE "/etc/security/limits.conf"
|
||||
#endif
|
||||
|
||||
#define LIMIT_ERR 1 /* error setting a limit */
|
||||
#define LOGIN_ERR 2 /* too many logins err */
|
||||
|
||||
/* Counts the number of user logins and check against the limit*/
|
||||
static int check_logins(const char *name, int limit, int ctrl)
|
||||
{
|
||||
struct utmp *ut;
|
||||
unsigned int count;
|
||||
|
||||
if (ctrl & PAM_DEBUG_ARG) {
|
||||
_pam_log(LOG_DEBUG, "checking logins for '%s' / %d\n", name,limit);
|
||||
}
|
||||
|
||||
if (limit < 0)
|
||||
return 0; /* no limits imposed */
|
||||
if (limit == 0) /* maximum 0 logins ? */ {
|
||||
_pam_log(LOG_WARNING, "No logins allowed for '%s'\n", name);
|
||||
return LOGIN_ERR;
|
||||
}
|
||||
|
||||
setutent();
|
||||
count = 0;
|
||||
while((ut = getutent())) {
|
||||
#ifdef USER_PROCESS
|
||||
if (ut->ut_type != USER_PROCESS)
|
||||
continue;
|
||||
#endif
|
||||
if (ut->UT_USER[0] == '\0')
|
||||
continue;
|
||||
if (!flag_numsyslogins
|
||||
&& strncmp(name, ut->UT_USER, sizeof(ut->UT_USER)) != 0)
|
||||
continue;
|
||||
if (++count >= limit)
|
||||
break;
|
||||
}
|
||||
endutent();
|
||||
if (count >= limit) {
|
||||
if (name) {
|
||||
_pam_log(LOG_WARNING, "Too many logins (max %d) for %s",
|
||||
limit, name);
|
||||
} else {
|
||||
_pam_log(LOG_WARNING, "Too many system logins (max %d)", limit);
|
||||
}
|
||||
return LOGIN_ERR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* checks if a user is on a list of members of the GID 0 group */
|
||||
static int is_on_list(char * const *list, const char *member)
|
||||
{
|
||||
while (*list) {
|
||||
if (strcmp(*list, member) == 0)
|
||||
return 1;
|
||||
list++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks if a user is a member of a group */
|
||||
static int is_on_group(const char *user_name, const char *group_name)
|
||||
{
|
||||
struct passwd *pwd;
|
||||
struct group *grp, *pgrp;
|
||||
char uname[LINE_LENGTH], gname[LINE_LENGTH];
|
||||
|
||||
if (!strlen(user_name))
|
||||
return 0;
|
||||
if (!strlen(group_name))
|
||||
return 0;
|
||||
memset(uname, 0, sizeof(uname));
|
||||
strncpy(uname, user_name, LINE_LENGTH);
|
||||
memset(gname, 0, sizeof(gname));
|
||||
strncpy(gname, group_name, LINE_LENGTH);
|
||||
|
||||
setpwent();
|
||||
pwd = getpwnam(uname);
|
||||
endpwent();
|
||||
if (!pwd)
|
||||
return 0;
|
||||
|
||||
/* the info about this group */
|
||||
setgrent();
|
||||
grp = getgrnam(gname);
|
||||
endgrent();
|
||||
if (!grp)
|
||||
return 0;
|
||||
|
||||
/* first check: is a member of the group_name group ? */
|
||||
if (is_on_list(grp->gr_mem, uname))
|
||||
return 1;
|
||||
|
||||
/* next check: user primary group is group_name ? */
|
||||
setgrent();
|
||||
pgrp = getgrgid(pwd->pw_gid);
|
||||
endgrent();
|
||||
if (!pgrp)
|
||||
return 0;
|
||||
if (!strcmp(pgrp->gr_name, gname))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_limits(void)
|
||||
{
|
||||
int retval = PAM_SUCCESS;
|
||||
|
||||
D(("called."));
|
||||
|
||||
retval |= getrlimit(RLIMIT_CPU, &limits[RLIMIT_CPU].limit);
|
||||
limits[RLIMIT_CPU].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_CPU].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_FSIZE, &limits[RLIMIT_FSIZE].limit);
|
||||
limits[RLIMIT_FSIZE].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_FSIZE].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_DATA, &limits[RLIMIT_DATA].limit);
|
||||
limits[RLIMIT_DATA].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_DATA].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_STACK, &limits[RLIMIT_STACK].limit);
|
||||
limits[RLIMIT_STACK].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_STACK].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_CORE, &limits[RLIMIT_CORE].limit);
|
||||
limits[RLIMIT_CORE].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_CORE].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_RSS, &limits[RLIMIT_RSS].limit);
|
||||
limits[RLIMIT_RSS].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_RSS].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_NPROC, &limits[RLIMIT_NPROC].limit);
|
||||
limits[RLIMIT_NPROC].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_NPROC].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_NOFILE, &limits[RLIMIT_NOFILE].limit);
|
||||
limits[RLIMIT_NOFILE].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_NOFILE].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_MEMLOCK, &limits[RLIMIT_MEMLOCK].limit);
|
||||
limits[RLIMIT_MEMLOCK].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_MEMLOCK].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
retval |= getrlimit(RLIMIT_AS, &limits[RLIMIT_AS].limit);
|
||||
limits[RLIMIT_AS].src_soft = LIMITS_DEF_NONE;
|
||||
limits[RLIMIT_AS].src_hard = LIMITS_DEF_NONE;
|
||||
|
||||
login_limit = -2;
|
||||
login_limit_def = LIMITS_DEF_NONE;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void process_limit(int source, const char *lim_type,
|
||||
const char *lim_item, const char *lim_value,
|
||||
int ctrl)
|
||||
{
|
||||
int limit_item;
|
||||
int limit_type = 0;
|
||||
long limit_value;
|
||||
char **endptr = (char **) &lim_value;
|
||||
const char *value_orig = lim_value;
|
||||
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG, "%s: processing(%d) %s %s %s\n",
|
||||
__FUNCTION__,source,lim_type,lim_item,lim_value);
|
||||
|
||||
if (strcmp(lim_item, "cpu") == 0)
|
||||
limit_item = RLIMIT_CPU;
|
||||
else if (strcmp(lim_item, "fsize") == 0)
|
||||
limit_item = RLIMIT_FSIZE;
|
||||
else if (strcmp(lim_item, "data") == 0)
|
||||
limit_item = RLIMIT_DATA;
|
||||
else if (strcmp(lim_item, "stack") == 0)
|
||||
limit_item = RLIMIT_STACK;
|
||||
else if (strcmp(lim_item, "core") == 0)
|
||||
limit_item = RLIMIT_CORE;
|
||||
else if (strcmp(lim_item, "rss") == 0)
|
||||
limit_item = RLIMIT_RSS;
|
||||
else if (strcmp(lim_item, "nproc") == 0)
|
||||
limit_item = RLIMIT_NPROC;
|
||||
else if (strcmp(lim_item, "nofile") == 0)
|
||||
limit_item = RLIMIT_NOFILE;
|
||||
else if (strcmp(lim_item, "memlock") == 0)
|
||||
limit_item = RLIMIT_MEMLOCK;
|
||||
else if (strcmp(lim_item, "as") == 0)
|
||||
limit_item = RLIMIT_AS;
|
||||
else if (strcmp(lim_item, "maxlogins") == 0) {
|
||||
limit_item = LIMIT_LOGIN;
|
||||
flag_numsyslogins = 0;
|
||||
} else if (strcmp(lim_item, "maxsyslogins") == 0) {
|
||||
limit_item = LIMIT_NUMSYSLOGINS;
|
||||
flag_numsyslogins = 1;
|
||||
} else {
|
||||
_pam_log(LOG_DEBUG,"unknown limit item '%s'", lim_item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(lim_type,"soft")==0)
|
||||
limit_type=LIMIT_SOFT;
|
||||
else if (strcmp(lim_type, "hard")==0)
|
||||
limit_type=LIMIT_HARD;
|
||||
else if (strcmp(lim_type,"-")==0)
|
||||
limit_type=LIMIT_SOFT | LIMIT_HARD;
|
||||
else if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS) {
|
||||
_pam_log(LOG_DEBUG,"unknown limit type '%s'", lim_type);
|
||||
return;
|
||||
}
|
||||
|
||||
limit_value = strtol(lim_value, endptr, 10);
|
||||
if (limit_value == 0 && value_orig == *endptr) { /* no chars read */
|
||||
if (strcmp(lim_value,"-") != 0) {
|
||||
_pam_log(LOG_DEBUG,"wrong limit value '%s'", lim_value);
|
||||
return;
|
||||
} else
|
||||
if (limit_item != LIMIT_LOGIN) {
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG,
|
||||
"'-' limit value valid for maxlogins type only");
|
||||
return;
|
||||
} else
|
||||
limit_value = -1;
|
||||
}
|
||||
|
||||
switch(limit_item) {
|
||||
case RLIMIT_CPU:
|
||||
limit_value *= 60;
|
||||
break;
|
||||
case RLIMIT_FSIZE:
|
||||
case RLIMIT_DATA:
|
||||
case RLIMIT_STACK:
|
||||
case RLIMIT_CORE:
|
||||
case RLIMIT_RSS:
|
||||
case RLIMIT_MEMLOCK:
|
||||
case RLIMIT_AS:
|
||||
limit_value *= 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
if (limit_item != LIMIT_LOGIN && limit_item != LIMIT_NUMSYSLOGINS) {
|
||||
if (limit_type & LIMIT_SOFT)
|
||||
if (limits[limit_item].src_soft < source)
|
||||
return;
|
||||
else {
|
||||
limits[limit_item].limit.rlim_cur = limit_value;
|
||||
limits[limit_item].src_soft = source;
|
||||
}
|
||||
if (limit_type & LIMIT_HARD)
|
||||
if (limits[limit_item].src_hard < source)
|
||||
return;
|
||||
else {
|
||||
limits[limit_item].limit.rlim_max = limit_value;
|
||||
limits[limit_item].src_hard = source;
|
||||
}
|
||||
} else
|
||||
if (login_limit_def < source)
|
||||
return;
|
||||
else {
|
||||
login_limit = limit_value;
|
||||
login_limit_def = source;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int parse_config_file(const char *uname, int ctrl)
|
||||
{
|
||||
FILE *fil;
|
||||
char buf[LINE_LENGTH];
|
||||
|
||||
#define CONF_FILE (conf_file[0])?conf_file:LIMITS_FILE
|
||||
/* check for the LIMITS_FILE */
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG,"reading settings from '%s'", CONF_FILE);
|
||||
fil = fopen(CONF_FILE, "r");
|
||||
if (fil == NULL) {
|
||||
_pam_log (LOG_WARNING, "can not read settings from %s", CONF_FILE);
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
#undef CONF_FILE
|
||||
|
||||
/* init things */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
/* start the show */
|
||||
while (fgets(buf, LINE_LENGTH, fil) != NULL) {
|
||||
char domain[LINE_LENGTH];
|
||||
char ltype[LINE_LENGTH];
|
||||
char item[LINE_LENGTH];
|
||||
char value[LINE_LENGTH];
|
||||
int i,j;
|
||||
char *tptr;
|
||||
|
||||
tptr = buf;
|
||||
/* skip the leading white space */
|
||||
while (*tptr && isspace(*tptr))
|
||||
tptr++;
|
||||
strcpy(buf, (const char *)tptr);
|
||||
|
||||
/* Rip off the comments */
|
||||
tptr = strchr(buf,'#');
|
||||
if (tptr)
|
||||
*tptr = '\0';
|
||||
/* Rip off the newline char */
|
||||
tptr = strchr(buf,'\n');
|
||||
if (tptr)
|
||||
*tptr = '\0';
|
||||
/* Anything left ? */
|
||||
if (!strlen(buf)) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(domain, 0, sizeof(domain));
|
||||
memset(ltype, 0, sizeof(ltype));
|
||||
memset(item, 0, sizeof(item));
|
||||
memset(value, 0, sizeof(value));
|
||||
|
||||
i = sscanf(buf,"%s%s%s%s", domain, ltype, item, value);
|
||||
for(j=0; j < strlen(domain); j++)
|
||||
domain[j]=tolower(domain[j]);
|
||||
for(j=0; j < strlen(ltype); j++)
|
||||
ltype[j]=tolower(ltype[j]);
|
||||
for(j=0; j < strlen(item); j++)
|
||||
item[j]=tolower(item[j]);
|
||||
for(j=0; j < strlen(value); j++)
|
||||
value[j]=tolower(value[j]);
|
||||
|
||||
if (i == 4) { /* a complete line */
|
||||
if (strcmp(uname, domain) == 0) /* this user have a limit */
|
||||
process_limit(LIMITS_DEF_USER, ltype, item, value, ctrl);
|
||||
else if (domain[0]=='@') {
|
||||
if (is_on_group(uname, domain+1))
|
||||
process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl);
|
||||
} else if (strcmp(domain, "*") == 0)
|
||||
process_limit(LIMITS_DEF_DEFAULT, ltype, item, value, ctrl);
|
||||
} else
|
||||
_pam_log(LOG_DEBUG,"invalid line '%s'", buf);
|
||||
}
|
||||
fclose(fil);
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
static int setup_limits(const char * uname, int ctrl)
|
||||
{
|
||||
int i;
|
||||
int retval = PAM_SUCCESS;
|
||||
|
||||
for (i=0; i<RLIM_NLIMITS; i++) {
|
||||
if (limits[i].limit.rlim_cur > limits[i].limit.rlim_max)
|
||||
limits[i].limit.rlim_cur = limits[i].limit.rlim_max;
|
||||
retval |= setrlimit(i, &limits[i].limit);
|
||||
}
|
||||
|
||||
if (retval != PAM_SUCCESS)
|
||||
retval = LIMIT_ERR;
|
||||
if (login_limit > 0) {
|
||||
if (check_logins(uname, login_limit, ctrl) == LOGIN_ERR)
|
||||
retval |= LOGIN_ERR;
|
||||
} else if (login_limit == 0)
|
||||
retval |= LOGIN_ERR;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* now the session stuff */
|
||||
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
int retval;
|
||||
char *user_name;
|
||||
struct passwd *pwd;
|
||||
int ctrl;
|
||||
|
||||
D(("called."));
|
||||
|
||||
memset(conf_file, 0, sizeof(conf_file));
|
||||
|
||||
ctrl = _pam_parse(argc, argv);
|
||||
retval = pam_get_item( pamh, PAM_USER, (void*) &user_name );
|
||||
if ( user_name == NULL || retval != PAM_SUCCESS ) {
|
||||
_pam_log(LOG_CRIT, "open_session - error recovering username");
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
setpwent();
|
||||
pwd = getpwnam(user_name);
|
||||
endpwent();
|
||||
if (!pwd) {
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_WARNING, "open_session username '%s' does not exist",
|
||||
user_name);
|
||||
return PAM_SESSION_ERR;
|
||||
}
|
||||
|
||||
/* do not impose limits on UID 0 accounts */
|
||||
if (!pwd->pw_uid) {
|
||||
if (ctrl & PAM_DEBUG_ARG)
|
||||
_pam_log(LOG_DEBUG, "user '%s' have UID 0 - no limits imposed",
|
||||
user_name);
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
retval = init_limits();
|
||||
if (retval != PAM_SUCCESS) {
|
||||
_pam_log(LOG_WARNING, "can not initialize");
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
|
||||
retval = parse_config_file(pwd->pw_name,ctrl);
|
||||
if (retval != PAM_SUCCESS) {
|
||||
_pam_log(LOG_WARNING, "error parsing the configuration file");
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
|
||||
retval = setup_limits(pwd->pw_name, ctrl);
|
||||
if (retval & LOGIN_ERR) {
|
||||
printf("\nToo many logins for '%s'\n",pwd->pw_name);
|
||||
sleep(2);
|
||||
return PAM_PERM_DENIED;
|
||||
}
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags,
|
||||
int argc, const char **argv)
|
||||
{
|
||||
/* nothing to do */
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_limits_modstruct = {
|
||||
"pam_limits",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
pam_sm_open_session,
|
||||
pam_sm_close_session,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) Cristian Gafton, 1996-1997, <gafton@redhat.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
@ -1,84 +0,0 @@
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
|
||||
TITLE=pam_listfile
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS)
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak dynamic/* static/*
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,25 +0,0 @@
|
||||
SUMMARY:
|
||||
pam_listfile:
|
||||
Checks a specified item against a list in a file.
|
||||
Options:
|
||||
* item=[tty|user|rhost|ruser|group|shell]
|
||||
* sense=[allow|deny] (action to take if found in file,
|
||||
if the item is NOT found in the file, then
|
||||
the opposite action is requested)
|
||||
* file=/the/file/to/get/the/list/from
|
||||
* onerr=[succeed|fail] (if something weird happens
|
||||
such as unable to open the file, what to do?)
|
||||
* apply=[user|@group]
|
||||
restrict the user class for which the restriction
|
||||
apply. Note that with item=[user|ruser|group] this
|
||||
does not make sense, but for item=[tty|rhost|shell]
|
||||
it have a meaning. (Cristian Gafton)
|
||||
|
||||
Also checks to make sure that the list file is a plain
|
||||
file and not world writable.
|
||||
|
||||
- Elliot Lee <sopwith@redhat.com>, Red Hat Software.
|
||||
v0.9 August 16, 1996.
|
||||
|
||||
BUGS:
|
||||
Bugs?
|
@ -1,436 +0,0 @@
|
||||
/*
|
||||
* $Id: pam_listfile.c,v 1.6 1997/04/05 06:38:35 morgan Exp $
|
||||
*
|
||||
* $Log: pam_listfile.c,v $
|
||||
* Revision 1.6 1997/04/05 06:38:35 morgan
|
||||
* reformat mostly
|
||||
*
|
||||
* Revision 1.5 1997/02/15 17:29:41 morgan
|
||||
* removed fixed length buffer in logging
|
||||
*
|
||||
* Revision 1.4 1997/01/04 20:32:10 morgan
|
||||
* ammendments for pam_listfile handling
|
||||
*
|
||||
* Revision 1.3 1996/11/10 21:02:08 morgan
|
||||
* compiles with .53
|
||||
*
|
||||
* Revision 1.2 1996/09/05 06:22:58 morgan
|
||||
* Michael's patches
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* by Elliot Lee <sopwith@redhat.com>, Red Hat Software.
|
||||
* July 25, 1996.
|
||||
* This code shamelessly ripped from the pam_rootok module.
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
# define _SVID_SOURCE
|
||||
# define _BSD_SOURCE
|
||||
# define __USE_BSD
|
||||
# define __USE_SVID
|
||||
# define __USE_MISC
|
||||
# define _GNU_SOURCE
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* here, we make a definition for the externally accessible function
|
||||
* in this file (this definition is required for static a module
|
||||
* but strongly encouraged generally) it is used to instruct the
|
||||
* modules include file to define the function prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
/* some syslogging */
|
||||
|
||||
static void _pam_log(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("PAM-listfile", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
/* checks if a user is on a list of members */
|
||||
static int is_on_list(char * const *list, const char *member)
|
||||
{
|
||||
while (*list) {
|
||||
if (strcmp(*list, member) == 0)
|
||||
return 1;
|
||||
list++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks if a user is a member of a group */
|
||||
static int is_on_group(const char *user_name, const char *group_name)
|
||||
{
|
||||
struct passwd *pwd;
|
||||
struct group *grp, *pgrp;
|
||||
char uname[BUFSIZ], gname[BUFSIZ];
|
||||
|
||||
if (!strlen(user_name))
|
||||
return 0;
|
||||
if (!strlen(group_name))
|
||||
return 0;
|
||||
bzero(uname, sizeof(uname));
|
||||
strncpy(uname, user_name, BUFSIZ-1);
|
||||
bzero(gname, sizeof(gname));
|
||||
strncpy(gname, group_name, BUFSIZ-1);
|
||||
|
||||
setpwent();
|
||||
pwd = getpwnam(uname);
|
||||
endpwent();
|
||||
if (!pwd)
|
||||
return 0;
|
||||
|
||||
/* the info about this group */
|
||||
setgrent();
|
||||
grp = getgrnam(gname);
|
||||
endgrent();
|
||||
if (!grp)
|
||||
return 0;
|
||||
|
||||
/* first check: is a member of the group_name group ? */
|
||||
if (is_on_list(grp->gr_mem, uname))
|
||||
return 1;
|
||||
|
||||
/* next check: user primary group is group_name ? */
|
||||
setgrent();
|
||||
pgrp = getgrgid(pwd->pw_gid);
|
||||
endgrent();
|
||||
if (!pgrp)
|
||||
return 0;
|
||||
if (!strcmp(pgrp->gr_name, gname))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- authentication management functions (only) --- */
|
||||
|
||||
/* Extended Items that are not directly available via pam_get_item() */
|
||||
#define EI_GROUP (1 << 0)
|
||||
#define EI_SHELL (1 << 1)
|
||||
|
||||
/* Constants for apply= parameter */
|
||||
#define APPLY_TYPE_NULL 0
|
||||
#define APPLY_TYPE_NONE 1
|
||||
#define APPLY_TYPE_USER 2
|
||||
#define APPLY_TYPE_GROUP 3
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
{
|
||||
int retval, i, citem=0, extitem=0, onerr=PAM_SERVICE_ERR, sense=2;
|
||||
const char *citemp;
|
||||
char *ifname=NULL;
|
||||
char aline[256];
|
||||
char mybuf[256],myval[256];
|
||||
struct stat fileinfo;
|
||||
FILE *inf;
|
||||
char apply_val[256];
|
||||
int apply_type;
|
||||
|
||||
/* Stuff for "extended" items */
|
||||
struct passwd *userinfo;
|
||||
struct group *grpinfo;
|
||||
char *itemlist[256]; /* Maximum of 256 items */
|
||||
|
||||
D(("called."));
|
||||
|
||||
apply_type=APPLY_TYPE_NULL;
|
||||
memset(apply_val,0,sizeof(apply_val));
|
||||
|
||||
for(i=0; i < argc; i++) {
|
||||
{
|
||||
char *junk;
|
||||
junk = (char *) malloc(strlen(argv[i])+1);
|
||||
if (junk == NULL) {
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
strcpy(junk,argv[i]);
|
||||
strncpy(mybuf,strtok(junk,"="),255);
|
||||
strncpy(myval,strtok(NULL,"="),255);
|
||||
free(junk);
|
||||
}
|
||||
if(!strcmp(mybuf,"onerr"))
|
||||
if(!strcmp(myval,"succeed"))
|
||||
onerr = PAM_SUCCESS;
|
||||
else if(!strcmp(myval,"fail"))
|
||||
onerr = PAM_SERVICE_ERR;
|
||||
else
|
||||
return PAM_SERVICE_ERR;
|
||||
else if(!strcmp(mybuf,"sense"))
|
||||
if(!strcmp(myval,"allow"))
|
||||
sense=0;
|
||||
else if(!strcmp(myval,"deny"))
|
||||
sense=1;
|
||||
else
|
||||
return onerr;
|
||||
else if(!strcmp(mybuf,"file")) {
|
||||
ifname = (char *)malloc(strlen(myval)+1);
|
||||
strcpy(ifname,myval);
|
||||
} else if(!strcmp(mybuf,"item"))
|
||||
if(!strcmp(myval,"user"))
|
||||
citem = PAM_USER;
|
||||
else if(!strcmp(myval,"tty"))
|
||||
citem = PAM_TTY;
|
||||
else if(!strcmp(myval,"rhost"))
|
||||
citem = PAM_RHOST;
|
||||
else if(!strcmp(myval,"ruser"))
|
||||
citem = PAM_RUSER;
|
||||
else { /* These items are related to the user, but are not
|
||||
directly gettable with pam_get_item */
|
||||
citem = PAM_USER;
|
||||
if(!strcmp(myval,"group"))
|
||||
extitem = EI_GROUP;
|
||||
else if(!strcmp(myval,"shell"))
|
||||
extitem = EI_SHELL;
|
||||
else
|
||||
citem = 0;
|
||||
} else if(!strcmp(mybuf,"apply")) {
|
||||
apply_type=APPLY_TYPE_NONE;
|
||||
if (myval[0]=='@') {
|
||||
apply_type=APPLY_TYPE_GROUP;
|
||||
strncpy(apply_val,myval+1,sizeof(apply_val)-1);
|
||||
} else {
|
||||
apply_type=APPLY_TYPE_USER;
|
||||
strncpy(apply_val,myval,sizeof(apply_val)-1);
|
||||
}
|
||||
} else {
|
||||
_pam_log(LOG_ERR,"Unknown option: %s",mybuf);
|
||||
return onerr;
|
||||
}
|
||||
}
|
||||
|
||||
if(!citem) {
|
||||
_pam_log(LOG_ERR,"Unknown item or item not specified");
|
||||
return onerr;
|
||||
} else if(!ifname) {
|
||||
_pam_log(LOG_ERR,"List filename not specified");
|
||||
return onerr;
|
||||
} else if(sense == 2) {
|
||||
_pam_log(LOG_ERR,"Unknown sense or sense not specified");
|
||||
return onerr;
|
||||
} else if(
|
||||
(apply_type==APPLY_TYPE_NONE) ||
|
||||
((apply_type!=APPLY_TYPE_NULL) && (*apply_val=='\0'))
|
||||
) {
|
||||
_pam_log(LOG_ERR,"Invalid usage for apply= parameter");
|
||||
return onerr;
|
||||
}
|
||||
|
||||
/* Check if it makes sense to use the apply= parameter */
|
||||
if (apply_type != APPLY_TYPE_NULL) {
|
||||
if((citem==PAM_USER) || (citem==PAM_RUSER)) {
|
||||
_pam_log(LOG_WARNING,"Non-sense use for apply= parameter");
|
||||
apply_type=APPLY_TYPE_NULL;
|
||||
}
|
||||
if(extitem && (extitem==EI_GROUP)) {
|
||||
_pam_log(LOG_WARNING,"Non-sense use for apply= parameter");
|
||||
apply_type=APPLY_TYPE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Short-circuit - test if this session apply for this user */
|
||||
{
|
||||
const char *user_name;
|
||||
int rval;
|
||||
|
||||
rval=pam_get_user(pamh,&user_name,NULL);
|
||||
if((rval==PAM_SUCCESS) && user_name[0]) {
|
||||
/* Got it ? Valid ? */
|
||||
if(apply_type==APPLY_TYPE_USER) {
|
||||
if(strcmp(user_name, apply_val)) {
|
||||
/* Does not apply to this user */
|
||||
#ifdef DEBUG
|
||||
_pam_log(LOG_DEBUG,"don't apply: apply=%s, user=%s",
|
||||
apply_val,user_name);
|
||||
#endif /* DEBUG */
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
} else if(apply_type==APPLY_TYPE_GROUP) {
|
||||
if(!is_on_group(user_name,apply_val)) {
|
||||
/* Not a member of apply= group */
|
||||
#ifdef DEBUG
|
||||
_pam_log(LOG_DEBUG,"don't apply: %s not a member of group %s",
|
||||
user_name,apply_val);
|
||||
#endif /* DEBUG */
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = pam_get_item(pamh,citem,(const void **)&citemp);
|
||||
if(retval != PAM_SUCCESS) {
|
||||
return onerr;
|
||||
}
|
||||
if((citem == PAM_USER) && !citemp) {
|
||||
pam_get_user(pamh,&citemp,NULL);
|
||||
if (retval != PAM_SUCCESS)
|
||||
return PAM_SERVICE_ERR;
|
||||
}
|
||||
|
||||
if(!citemp || (strlen(citemp) <= 0)) {
|
||||
/* The item was NULL - we are sure not to match */
|
||||
return sense?PAM_SUCCESS:PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
if(extitem) {
|
||||
switch(extitem) {
|
||||
case EI_GROUP:
|
||||
setpwent();
|
||||
userinfo = getpwnam(citemp);
|
||||
setgrent();
|
||||
grpinfo = getgrgid(userinfo->pw_gid);
|
||||
itemlist[0] = x_strdup(grpinfo->gr_name);
|
||||
setgrent();
|
||||
for (i=1; (i < sizeof(itemlist)/sizeof(itemlist[0])-1) &&
|
||||
(grpinfo = getgrent()); ) {
|
||||
if (is_on_list(grpinfo->gr_mem,citemp)) {
|
||||
itemlist[i++] = x_strdup(grpinfo->gr_name);
|
||||
}
|
||||
}
|
||||
itemlist[i] = NULL;
|
||||
endgrent();
|
||||
endpwent();
|
||||
break;
|
||||
case EI_SHELL:
|
||||
setpwent();
|
||||
userinfo = getpwnam(citemp); /* Assume that we have already gotten
|
||||
PAM_USER in pam_get_item() - a valid
|
||||
assumption since citem gets set to
|
||||
PAM_USER in the extitem switch */
|
||||
citemp = userinfo->pw_shell;
|
||||
endpwent();
|
||||
break;
|
||||
default:
|
||||
_pam_log(LOG_ERR,"Internal weirdness, unknown extended item %d",
|
||||
extitem);
|
||||
return onerr;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
_pam_log(LOG_INFO,"Got file = %s, item = %d, value = %s, sense = %d",
|
||||
ifname, citem, citemp, sense);
|
||||
#endif
|
||||
if(lstat(ifname,&fileinfo)) {
|
||||
_pam_log(LOG_ERR,
|
||||
"Couldn't open %s",ifname);
|
||||
return onerr;
|
||||
}
|
||||
|
||||
if((fileinfo.st_mode & S_IWOTH)
|
||||
|| !S_ISREG(fileinfo.st_mode)) {
|
||||
/* If the file is world writable or is not a
|
||||
normal file, return error */
|
||||
_pam_log(LOG_ERR,
|
||||
"%s is either world writable or not a normal file",
|
||||
ifname);
|
||||
return PAM_AUTH_ERR;
|
||||
}
|
||||
|
||||
inf = fopen(ifname,"r");
|
||||
if(inf == NULL) { /* Check that we opened it successfully */
|
||||
if (onerr == PAM_SERVICE_ERR) {
|
||||
/* Only report if it's an error... */
|
||||
_pam_log(LOG_ERR, "Error opening %s", ifname);
|
||||
}
|
||||
return onerr;
|
||||
}
|
||||
/* There should be no more errors from here on */
|
||||
retval=PAM_AUTH_ERR;
|
||||
/* This loop assumes that PAM_SUCCESS == 0
|
||||
and PAM_AUTH_ERR != 0 */
|
||||
#ifdef DEBUG
|
||||
assert(PAM_SUCCESS == 0);
|
||||
assert(PAM_AUTH_ERR != 0);
|
||||
#endif
|
||||
if(extitem == EI_GROUP) {
|
||||
while((fgets(aline,255,inf) != NULL)
|
||||
&& retval) {
|
||||
if(aline[strlen(aline) - 1] == '\n')
|
||||
aline[strlen(aline) - 1] = '\0';
|
||||
for(i=0;itemlist[i];)
|
||||
/* If any of the items match, strcmp() == 0, and we get out
|
||||
of this loop */
|
||||
retval = (strcmp(aline,itemlist[i++]) && retval);
|
||||
}
|
||||
for(i=0;itemlist[i];)
|
||||
free(itemlist[i++]);
|
||||
} else {
|
||||
while((fgets(aline,255,inf) != NULL)
|
||||
&& retval) {
|
||||
if(aline[strlen(aline) - 1] == '\n')
|
||||
aline[strlen(aline) - 1] = '\0';
|
||||
retval = strcmp(aline,citemp);
|
||||
}
|
||||
}
|
||||
fclose(inf);
|
||||
free(ifname);
|
||||
if(retval) {
|
||||
#ifdef DEBUG
|
||||
syslog(LOG_INFO,"Returning %d, retval = %d",
|
||||
sense?PAM_AUTH_ERR:PAM_SUCCESS, retval);
|
||||
#endif
|
||||
return sense?PAM_SUCCESS:PAM_AUTH_ERR;
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
syslog(LOG_INFO,"Returning %d, retval = %d",
|
||||
sense?PAM_SUCCESS:PAM_AUTH_ERR, retval);
|
||||
#endif
|
||||
return sense?PAM_AUTH_ERR:PAM_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||
{
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_listfile_modstruct = {
|
||||
"pam_listfile",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* end of module definition */
|
||||
|
@ -1,107 +0,0 @@
|
||||
#
|
||||
# $Id: Makefile,v 1.3 1997/04/05 06:37:45 morgan Exp $
|
||||
#
|
||||
# This Makefile controls a build process of $(TITLE) module for
|
||||
# Linux-PAM. You should not modify this Makefile (unless you know
|
||||
# what you are doing!).
|
||||
#
|
||||
# $Log: Makefile,v $
|
||||
# Revision 1.3 1997/04/05 06:37:45 morgan
|
||||
# fakeroot
|
||||
#
|
||||
# Revision 1.2 1997/02/15 16:07:22 morgan
|
||||
# optional libpwdb compilation
|
||||
#
|
||||
# Revision 1.1 1997/01/04 20:32:52 morgan
|
||||
# Initial revision
|
||||
#
|
||||
#
|
||||
#
|
||||
# Created by Andrew Morgan <morgan@parc.power.net> 1996/12/8
|
||||
#
|
||||
|
||||
TITLE=pam_mail
|
||||
|
||||
ifndef STATIC
|
||||
ifeq ($(HAVE_PWDBLIB),yes)
|
||||
CFLAGS += -DWANT_PWDB
|
||||
EXTRALIB = -lpwdb
|
||||
endif
|
||||
endif
|
||||
|
||||
#
|
||||
|
||||
LIBSRC = $(TITLE).c
|
||||
LIBOBJ = $(TITLE).o
|
||||
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
|
||||
LIBOBJS = $(addprefix static/,$(LIBOBJ))
|
||||
|
||||
dynamic/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
static/%.o : %.c
|
||||
$(CC) $(CFLAGS) $(STATIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
|
||||
|
||||
|
||||
ifdef DYNAMIC
|
||||
LIBSHARED = $(TITLE).so
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
LIBSTATIC = lib$(TITLE).o
|
||||
endif
|
||||
|
||||
####################### don't edit below #######################
|
||||
|
||||
dummy:
|
||||
|
||||
@echo "**** This is not a top-level Makefile "
|
||||
exit
|
||||
|
||||
all: dirs $(LIBSHARED) $(LIBSTATIC) register
|
||||
|
||||
dirs:
|
||||
ifdef DYNAMIC
|
||||
$(MKDIR) ./dynamic
|
||||
endif
|
||||
ifdef STATIC
|
||||
$(MKDIR) ./static
|
||||
endif
|
||||
|
||||
register:
|
||||
ifdef STATIC
|
||||
( cd .. ; ./register_static $(TITLE) $(TITLE)/$(LIBSTATIC) )
|
||||
endif
|
||||
|
||||
ifdef DYNAMIC
|
||||
$(LIBOBJD): $(LIBSRC)
|
||||
|
||||
$(LIBSHARED): $(LIBOBJD)
|
||||
$(LD_D) -o $@ $(LIBOBJD) $(EXTRALIB)
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(LIBOBJS): $(LIBSRC)
|
||||
|
||||
$(LIBSTATIC): $(LIBOBJS)
|
||||
$(LD) -r -o $@ $(LIBOBJS) $(EXTRALIB)
|
||||
endif
|
||||
|
||||
install: all
|
||||
$(MKDIR) $(FAKEROOT)$(SECUREDIR)
|
||||
ifdef DYNAMIC
|
||||
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
|
||||
endif
|
||||
|
||||
remove:
|
||||
rm -f $(FAKEROOT)$(SECUREDIR)/$(TITLE).so
|
||||
|
||||
clean:
|
||||
rm -f $(LIBOBJD) $(LIBOBJS) core *~
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.a *.o *.so *.bak dynamic/* static/*
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
@ -1,401 +0,0 @@
|
||||
/* pam_mail module */
|
||||
|
||||
/*
|
||||
* $Id: pam_mail.c,v 1.2 1997/02/15 16:06:14 morgan Exp morgan $
|
||||
*
|
||||
* Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11
|
||||
* $HOME additions by David Kinchlea <kinch@kinch.ark.com> 1997/1/7
|
||||
*
|
||||
* $Log: pam_mail.c,v $
|
||||
* Revision 1.2 1997/02/15 16:06:14 morgan
|
||||
* session -> setcred, also added "~"=$HOME
|
||||
*
|
||||
* Revision 1.1 1997/01/04 20:33:02 morgan
|
||||
* Initial revision
|
||||
*/
|
||||
|
||||
#define DEFAULT_MAIL_DIRECTORY "/var/spool/mail"
|
||||
#define MAIL_FILE_FORMAT "%s/%s"
|
||||
#define MAIL_ENV_NAME "MAIL"
|
||||
#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s"
|
||||
#define YOUR_MAIL_FORMAT "You have %s mail in %s"
|
||||
|
||||
#ifdef linux
|
||||
# define _GNU_SOURCE
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <pwd.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef WANT_PWDB
|
||||
#include <pwdb/pwdb_public.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* here, we make a definition for the externally accessible function
|
||||
* in this file (this definition is required for static a module
|
||||
* but strongly encouraged generally) it is used to instruct the
|
||||
* modules include file to define the function prototypes.
|
||||
*/
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/_pam_macros.h>
|
||||
|
||||
/* some syslogging */
|
||||
|
||||
static void _log_err(int err, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
openlog("PAM-mail", LOG_CONS|LOG_PID, LOG_AUTH);
|
||||
vsyslog(err, format, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
/* argument parsing */
|
||||
|
||||
#define PAM_DEBUG_ARG 01
|
||||
#define PAM_NO_LOGIN 02
|
||||
#define PAM_LOGOUT_TOO 04
|
||||
#define PAM_NEW_MAIL_DIR 010
|
||||
#define PAM_MAIL_SILENT 020
|
||||
#define PAM_NO_ENV 040
|
||||
#define PAM_HOME_MAIL 0100
|
||||
#define PAM_EMPTY_TOO 0200
|
||||
|
||||
static int _pam_parse(int flags, int argc, const char **argv, char **maildir)
|
||||
{
|
||||
int ctrl=0;
|
||||
|
||||
if (flags & PAM_SILENT) {
|
||||
ctrl |= PAM_MAIL_SILENT;
|
||||
}
|
||||
|
||||
/* step through arguments */
|
||||
for (; argc-- > 0; ++argv) {
|
||||
|
||||
/* generic options */
|
||||
|
||||
if (!strcmp(*argv,"debug"))
|
||||
ctrl |= PAM_DEBUG_ARG;
|
||||
else if (!strncmp(*argv,"dir=",4)) {
|
||||
*maildir = x_strdup(4+*argv);
|
||||
if (*maildir != NULL) {
|
||||
D(("new mail directory: %s", *maildir));
|
||||
ctrl |= PAM_NEW_MAIL_DIR;
|
||||
} else {
|
||||
_log_err(LOG_CRIT,
|
||||
"failed to duplicate mail directory - ignored");
|
||||
}
|
||||
} else if (!strcmp(*argv,"close")) {
|
||||
ctrl |= PAM_LOGOUT_TOO;
|
||||
} else if (!strcmp(*argv,"nopen")) {
|
||||
ctrl |= PAM_NO_LOGIN;
|
||||
} else if (!strcmp(*argv,"noenv")) {
|
||||
ctrl |= PAM_NO_ENV;
|
||||
} else if (!strcmp(*argv,"empty")) {
|
||||
ctrl |= PAM_EMPTY_TOO;
|
||||
} else {
|
||||
_log_err(LOG_ERR,"pam_parse: unknown option; %s",*argv);
|
||||
}
|
||||
}
|
||||
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
/* a front end for conversations */
|
||||
|
||||
static int converse(pam_handle_t *pamh, int ctrl, int nargs
|
||||
, struct pam_message **message
|
||||
, struct pam_response **response)
|
||||
{
|
||||
int retval;
|
||||
struct pam_conv *conv;
|
||||
|
||||
D(("begin to converse"));
|
||||
|
||||
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
|
||||
if ( retval == PAM_SUCCESS ) {
|
||||
|
||||
retval = conv->conv(nargs, ( const struct pam_message ** ) message
|
||||
, response, conv->appdata_ptr);
|
||||
|
||||
D(("returned from application's conversation function"));
|
||||
|
||||
if (retval != PAM_SUCCESS && (PAM_DEBUG_ARG & ctrl) ) {
|
||||
_log_err(LOG_DEBUG, "conversation failure [%s]"
|
||||
, pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
} else {
|
||||
_log_err(LOG_ERR, "couldn't obtain coversation function [%s]"
|
||||
, pam_strerror(pamh, retval));
|
||||
}
|
||||
|
||||
D(("ready to return from module conversation"));
|
||||
|
||||
return retval; /* propagate error status */
|
||||
}
|
||||
|
||||
static int get_folder(pam_handle_t *pamh, int ctrl
|
||||
, char **path_mail, char **folder_p)
|
||||
{
|
||||
int retval;
|
||||
const char *user, *path;
|
||||
char *folder;
|
||||
const struct passwd *pwd=NULL;
|
||||
|
||||
retval = pam_get_user(pamh, &user, NULL);
|
||||
if (retval != PAM_SUCCESS || user == NULL) {
|
||||
_log_err(LOG_ERR, "no user specified");
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
|
||||
if (ctrl & PAM_NEW_MAIL_DIR) {
|
||||
path = *path_mail;
|
||||
if (*path == '~') { /* support for $HOME delivery */
|
||||
pwd = getpwnam(user);
|
||||
if (pwd == NULL) {
|
||||
_log_err(LOG_ERR, "user [%s] unknown", user);
|
||||
_pam_overwrite(*path_mail);
|
||||
_pam_drop(*path_mail);
|
||||
return PAM_USER_UNKNOWN;
|
||||
}
|
||||
/*
|
||||
* "~/xxx" and "~xxx" are treated as same
|
||||
*/
|
||||
if (!*++path || (*path == '/' && !*++path)) {
|
||||
_log_err(LOG_ALERT, "badly formed mail path [%s]", *path_mail);
|
||||
_pam_overwrite(*path_mail);
|
||||
_pam_drop(*path_mail);
|
||||
return PAM_ABORT;
|
||||
}
|
||||
ctrl |= PAM_HOME_MAIL;
|
||||
}
|
||||
} else {
|
||||
path = DEFAULT_MAIL_DIRECTORY;
|
||||
}
|
||||
|
||||
/* put folder together */
|
||||
|
||||
if (ctrl & PAM_HOME_MAIL) {
|
||||
folder = malloc(sizeof(MAIL_FILE_FORMAT)
|
||||
+strlen(pwd->pw_dir)+strlen(path));
|
||||
} else {
|
||||
folder = malloc(sizeof(MAIL_FILE_FORMAT)+strlen(path)+strlen(user));
|
||||
}
|
||||
|
||||
if (folder != NULL) {
|
||||
if (ctrl & PAM_HOME_MAIL) {
|
||||
sprintf(folder, MAIL_FILE_FORMAT, pwd->pw_dir, path);
|
||||
} else {
|
||||
sprintf(folder, MAIL_FILE_FORMAT, path, user);
|
||||
}
|
||||
D(("folder =[%s]", folder));
|
||||
}
|
||||
|
||||
/* tidy up */
|
||||
|
||||
_pam_overwrite(*path_mail);
|
||||
_pam_drop(*path_mail);
|
||||
user = NULL;
|
||||
|
||||
if (folder == NULL) {
|
||||
_log_err(LOG_CRIT, "out of memory for mail folder");
|
||||
return PAM_BUF_ERR;
|
||||
}
|
||||
|
||||
*folder_p = folder;
|
||||
folder = NULL;
|
||||
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
static const char *get_mail_status(int ctrl, const char *folder)
|
||||
{
|
||||
const char *type;
|
||||
struct stat mail_st;
|
||||
|
||||
if (stat(folder, &mail_st) == 0 && mail_st.st_size > 0) {
|
||||
type = (mail_st.st_atime < mail_st.st_mtime) ? "new":"old" ;
|
||||
} else if (ctrl & PAM_EMPTY_TOO) {
|
||||
type = "no";
|
||||
} else {
|
||||
type = NULL;
|
||||
}
|
||||
|
||||
memset(&mail_st, 0, sizeof(mail_st));
|
||||
D(("user has %s mail in %s folder", type, folder));
|
||||
return type;
|
||||
}
|
||||
|
||||
static int report_mail(pam_handle_t *pamh, int ctrl
|
||||
, const char *type, const char *folder)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!(ctrl & PAM_MAIL_SILENT)) {
|
||||
char *remark;
|
||||
|
||||
remark = malloc(sizeof(YOUR_MAIL_FORMAT)+strlen(type)+strlen(folder));
|
||||
if (remark == NULL) {
|
||||
retval = PAM_BUF_ERR;
|
||||
} else {
|
||||
struct pam_message msg[1], *mesg[1];
|
||||
struct pam_response *resp=NULL;
|
||||
|
||||
sprintf(remark, YOUR_MAIL_FORMAT, type, folder);
|
||||
|
||||
mesg[0] = &msg[0];
|
||||
msg[0].msg_style = PAM_TEXT_INFO;
|
||||
msg[0].msg = remark;
|
||||
|
||||
retval = converse(pamh, ctrl, 1, mesg, &resp);
|
||||
|
||||
_pam_overwrite(remark);
|
||||
_pam_drop(remark);
|
||||
if (resp)
|
||||
_pam_drop_reply(resp, 1);
|
||||
}
|
||||
} else {
|
||||
D(("keeping quiet"));
|
||||
retval = PAM_SUCCESS;
|
||||
}
|
||||
|
||||
D(("returning %s", pam_strerror(pamh, retval)));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* --- authentication management functions (only) --- */
|
||||
|
||||
/*
|
||||
* Cannot use mail to authenticate yourself
|
||||
*/
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
|
||||
,const char **argv)
|
||||
{
|
||||
return PAM_IGNORE;
|
||||
}
|
||||
|
||||
/*
|
||||
* MAIL is a "credential"
|
||||
*/
|
||||
|
||||
PAM_EXTERN
|
||||
int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc
|
||||
, const char **argv)
|
||||
{
|
||||
int retval, ctrl;
|
||||
char *path_mail=NULL, *folder;
|
||||
const char *type;
|
||||
|
||||
/*
|
||||
* this module (un)sets the MAIL environment variable, and checks if
|
||||
* the user has any new mail.
|
||||
*/
|
||||
|
||||
ctrl = _pam_parse(flags, argc, argv, &path_mail);
|
||||
|
||||
/* Do we have anything to do? */
|
||||
|
||||
if (!(flags & (PAM_ESTABLISH_CRED|PAM_DELETE_CRED))) {
|
||||
return PAM_SUCCESS;
|
||||
}
|
||||
|
||||
/* which folder? */
|
||||
|
||||
retval = get_folder(pamh, ctrl, &path_mail, &folder);
|
||||
if (retval != PAM_SUCCESS) {
|
||||
D(("failed to find folder"));
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* set the MAIL variable? */
|
||||
|
||||
if (!(ctrl & PAM_NO_ENV) && (flags & PAM_ESTABLISH_CRED)) {
|
||||
char *tmp;
|
||||
|
||||
tmp = malloc(strlen(folder)+sizeof(MAIL_ENV_FORMAT));
|
||||
if (tmp != NULL) {
|
||||
sprintf(tmp, MAIL_ENV_FORMAT, folder);
|
||||
D(("setting env: %s", tmp));
|
||||
retval = pam_putenv(pamh, tmp);
|
||||
_pam_overwrite(tmp);
|
||||
_pam_drop(tmp);
|
||||
if (retval != PAM_SUCCESS) {
|
||||
_pam_overwrite(folder);
|
||||
_pam_drop(folder);
|
||||
_log_err(LOG_CRIT, "unable to set " MAIL_ENV_NAME " variable");
|
||||
return retval;
|
||||
}
|
||||
} else {
|
||||
_log_err(LOG_CRIT, "no memory for " MAIL_ENV_NAME " variable");
|
||||
_pam_overwrite(folder);
|
||||
_pam_drop(folder);
|
||||
return retval;
|
||||
}
|
||||
} else {
|
||||
D(("not setting " MAIL_ENV_NAME " variable"));
|
||||
}
|
||||
|
||||
/*
|
||||
* OK. we've got the mail folder... what about its status?
|
||||
*/
|
||||
|
||||
if (((flags & PAM_ESTABLISH_CRED) && !(ctrl & PAM_NO_LOGIN))
|
||||
|| ((flags & PAM_DELETE_CRED) && (ctrl & PAM_LOGOUT_TOO))) {
|
||||
type = get_mail_status(ctrl, folder);
|
||||
if (type != NULL) {
|
||||
retval = report_mail(pamh, ctrl, type, folder);
|
||||
type = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete environment variable?
|
||||
*/
|
||||
|
||||
if (flags & PAM_DELETE_CRED) {
|
||||
(void) pam_putenv(pamh, MAIL_ENV_NAME);
|
||||
}
|
||||
|
||||
_pam_overwrite(folder); /* clean up */
|
||||
_pam_drop(folder);
|
||||
|
||||
/* indicate success or failure */
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef PAM_STATIC
|
||||
|
||||
/* static module data */
|
||||
|
||||
struct pam_module _pam_mail_modstruct = {
|
||||
"pam_mail",
|
||||
pam_sm_authenticate,
|
||||
pam_sm_setcred,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* end of module definition */
|
@ -1,12 +0,0 @@
|
||||
# $Id: README,v 1.1 1996/10/25 03:19:36 morgan Exp $
|
||||
#
|
||||
|
||||
This module always lets root in; it lets other users in only if the file
|
||||
/etc/nologin doesn't exist. In any case, if /etc/nologin exists, it's
|
||||
contents are displayed to the user.
|
||||
|
||||
module services provided:
|
||||
|
||||
auth _authentication and _setcred (blank)
|
||||
|
||||
Michael K. Johnson
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user