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:
John Polstra 1998-11-25 19:46:10 +00:00
parent 46d4978e39
commit 9748c8ad8f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=41336
163 changed files with 0 additions and 26807 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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.
-->

View File

@ -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 &lt;brucec@humbug.org.au&gt;
<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.
-->

View File

@ -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 &lt;gafton@redhat.com&gt;
<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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;kinch@kinch.ark.com&gt;
<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>&dollar;&lcub;string&rcub;</tt> syntax and (possibly
non-existent) <em/PAM_ITEM/s may be used in values using the
<tt>&commat;&lcub;string&rcub;</tt> syntax. Both the <tt>&dollar;</tt>
and <tt>&commat;</tt> characters can be backslash-escaped to be used
as literal values (as in <tt>&bsol;&dollar;</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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;shadow@dementia.org&gt;
<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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;gafton@redhat.com&gt; <newline>
Thanks are also due to Elliot Lee &lt;sopwith@redhat.com&gt;
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>&lt;domain&gt;</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>&lt;type&gt;</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>&lt;item&gt;</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.
-->

View File

@ -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>&lt;sopwith@cuc.edu&gt;</tt>
<tag><bf>Maintainer:</bf></tag>
Red Hat Software:<newline>
Michael K. Johnson &lt;johnsonm@redhat.com&gt; 1996/11/18<newline>
(if unavailable, contact Elliot Lee &lt;sopwith@cuc.edu&gt;).
<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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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/&tilde;/', 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.
-->

View File

@ -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 &lt;johnsonm@redhat.com&gt;<newline>
(based on code taken from a module written by Andrew G. Morgan
&lt;morgan@parc.power.net&gt;).
<tag><bf>Maintainer:</bf></tag>
Michael K. Johnson &lt;johnsonm@redhat.com&gt;
<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.
-->

View File

@ -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, &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;gafton@redhat.com&gt; <newline>
and Andrew G. Morgan &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;gafton@redhat.com&gt;
<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.
-->

View File

@ -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 &lt;longyear@netcom.com&gt;
<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 &lt;netdb.h&gt;</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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;sopwith@cuc.edu&gt;
<tag><bf>Maintainer:</bf></tag>
Red Hat Software:<newline>
<em/currently/ Michael K. Johnson &lt;johnsonm@redhat.com&gt;<newline>
(if unavailable, contact Elliot Lee &lt;sopwith@cuc.edu&gt;).
<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.
-->

View File

@ -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>&lt;morgan@parc.power.net&gt;</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/&amp;/ (logical AND) and <tt/|/ (logical OR). Two
examples are: <tt>!morgan&amp;!root</tt>, indicating that this rule
does not apply to the user <tt>morgan</tt> nor to <tt>root</tt>; and
<tt>tty*&amp;!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>&bsol;</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* &amp ; !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.
-->

View File

@ -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 &lt;morgan@parc.power.net&gt;
<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.
-->

View File

@ -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 &lt;gafton@redhat.com&gt;
<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.
-->

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
%%

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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 */
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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..
#########################################################################

View File

@ -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 $<

View File

@ -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
############################################################################

View File

@ -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.
#

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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.
*/

View File

@ -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 $<

View File

@ -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.

View File

@ -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

View File

@ -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 $<

View File

@ -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=\@

View File

@ -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

View File

@ -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 &quote 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 = &quote; /* 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 && (&quote != var->defval) &&
((retval = _expand_arg(pamh, &(var->defval))) != PAM_SUCCESS)) {
return retval;
}
if (var->override && (&quote != var->override) &&
((retval = _expand_arg(pamh, &(var->override))) != PAM_SUCCESS)) {
return retval;
}
/* Now its easy */
if (var->override && *(var->override) && &quote != 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 (&quote == 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 && (&quote != var->defval)) {
free(var->defval);
}
if (var->override && (&quote != 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 */

View File

@ -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=\@

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 $<

View File

@ -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);
}

View File

@ -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 $<

View File

@ -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

View File

@ -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 */

View File

@ -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 $<

View File

@ -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
#

View 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

View File

@ -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

View File

@ -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 $<

View File

@ -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 */

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View 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.
*/

View File

@ -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 $<

View File

@ -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?

View File

@ -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 */

View File

@ -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 $<

View File

@ -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 */

View File

@ -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