I have hacked pam_access to support Solaris 2.6 - 8 and HP-UX 11.00. To better ease the transition from logdaemon to pam_access, I also changed the access file to /etc/login.access. The attached patch will also cause the module to send mail when a user is denied. If you want to make use of this patch on a non-linux machine, here are the steps that I took: This PAM module came from Red Hat Linux 7.0's pam-0.72-26.src.rpm. On a Red Hat 7 box I did: rpm2cpio pam-0.72-26.src.rpm > pam.cpio scp pam.cpio <sun box> On the Sun, I then did: cpio -ilmudv pam.cpio gzip -dc pam-redhat-0.72-26.tar.gz | tar xvf - hack, hack, hack gmake # cp pam_access.so /lib/security/pam_access.so.1 # ln -s pam_access.so.1 /lib/security/pam_access.so /etc/pam.conf additions for Solaris 2.6: login account required /usr/lib/security/pam_access.so.1 dtlogin account required /usr/lib/security/pam_access.so.1 sshd account required /usr/lib/security/pam_access.so.1 other account required /usr/lib/security/pam_access.so.1 /etc/pam.conf additions for Solaris 7 and 8: login account required /usr/lib/security/$ISA/pam_access.so.1 dtlogin account required /usr/lib/security/$ISA/pam_access.so.1 other account required /usr/lib/security/$ISA/pam_access.so.1 sshd account required /usr/lib/security/$ISA/pam_access.so.1 /etc/pam.conf additions for HP-UX 11.00 login account required /usr/lib/security/pam_access.1 su account required /usr/lib/security/pam_access.1 dtlogin account required /usr/lib/security/pam_access.1 dtaction account required /usr/lib/security/pam_access.1 ftp account required /usr/lib/security/pam_access.1 sshd account required /usr/lib/security/pam_access.1 OTHER account required /usr/lib/security/pam_access.1 If I hosed something, I would be more than happy to hear about it. Mike
Index: Makefile =================================================================== RCS file: /aurproj/cns/src/cvs-repository/pam_access/Makefile,v retrieving revision 1.1 retrieving revision 1.6 diff -c -r1.1 -r1.6 *** Makefile 2000/11/21 14:50:32 1.1 --- Makefile 2000/12/07 19:15:13 1.6 *************** *** 1,4 **** ! # $Id: Makefile,v 1.1 2000/11/21 14:50:32 mgerdts Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know --- 1,4 ---- ! # $Id: Makefile,v 1.6 2000/12/07 19:15:13 mgerdts Exp $ # # This Makefile controls a build process of $(TITLE) module for # Linux-PAM. You should not modify this Makefile (unless you know *************** *** 6,28 **** # 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 --- 6,53 ---- # TITLE=pam_access ! CONFD=/etc export CONFD ! CONFILE=$(CONFD)/login.access export CONFILE + sysname=$(shell uname -s) # Convenient defaults for compiling independently of the full source # tree. ifndef FULL_LINUX_PAM_SOURCE_TREE + ifeq ($(sysname),SunOS) + OS_CFLAGS=-Dsolaris -DSOLARIS_PAM -D_POSIX_C_SOURCE + OS_CFLAGS+=-D_XPG4_2 -D__EXTENSIONS__ + OS_LDSHARED_FLAGS= + OS_LD_EXTRALIBS=-lpam + LD_D=ld -G -z redlocsym + OS_SO_SUFFIX = .so + endif + ifeq ($(sysname),Linux) + OS_CFLAGS=-Dlinux -DLINUX_PAM + OS_LD_EXTRALIBS= + LD_D=gcc -shared -Xlinker -x + OS_SO_SUFFIX = .so + endif + ifeq ($(sysname),HP-UX) + OS_CFLAGS = -Dhpux -D_INCLUDE_XOPEN_SOURCE + OS_CFLAGS += -D_INCLUDE_HPUX_SOURCE -D__STDC__ + OS_CFLAGS += -D_INCLUDE_XOPEN_SOURCE_EXTENDED + OS_FLAGS += -D_XPG4_EXTENDED + OS_CFLAGS += -Dvsyslog=myvsyslog + OS_LDSHARED_FLAGS= + OS_LD_EXTRALIBS=-lpam + OS_SO_SUFFIX = .1 + LD_D=ld -b -G + endif export DYNAMIC=-DPAM_DYNAMIC export CC=gcc ! export CFLAGS=-O2 $(OS_CFLAGS) \ -ansi -D_POSIX_SOURCE -Wall -Wwrite-strings \ -Wpointer-arith -Wcast-qual -Wcast-align -Wtraditional \ -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline \ -Wshadow -pedantic -fPIC ! MKDIR=mkdir -p endif LIBSRC = $(TITLE).c *************** *** 30,36 **** LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBOBJS = $(addprefix static/,$(LIBOBJ)) ! DEFS=-DCONFILE=\"$(CONFILE)\" CFLAGS += $(DEFS) -DNIS --- 55,61 ---- LIBOBJD = $(addprefix dynamic/,$(LIBOBJ)) LIBOBJS = $(addprefix static/,$(LIBOBJ)) ! DEFS=-DCONFILE=\"$(CONFILE)\" -DLOGMAIL_FROM=\"root\" -DLOGMAIL_TO=\"security\" CFLAGS += $(DEFS) -DNIS *************** *** 42,48 **** ifdef DYNAMIC ! LIBSHARED = $(TITLE).so endif ifdef STATIC LIBSTATIC = lib$(TITLE).o --- 67,73 ---- ifdef DYNAMIC ! LIBSHARED = $(TITLE).$(OS_SO_SUFFIX) endif ifdef STATIC LIBSTATIC = lib$(TITLE).o *************** *** 50,59 **** ####################### don't edit below ####################### - dummy: - @echo "**** This is not a top-level Makefile " - exit - all: dirs $(LIBSHARED) $(LIBSTATIC) register dirs: --- 75,80 ---- *************** *** 73,79 **** $(LIBOBJD): $(LIBSRC) $(LIBSHARED): $(LIBOBJD) ! $(LD_D) -o $@ $(LIBOBJD) -lnsl endif ifdef STATIC --- 94,100 ---- $(LIBOBJD): $(LIBSRC) $(LIBSHARED): $(LIBOBJD) ! $(LD_D) -o $@ $(LIBOBJD) -lnsl $(OS_LD_EXTRALIBS) endif ifdef STATIC Index: pam_access.c =================================================================== RCS file: /aurproj/cns/src/cvs-repository/pam_access/pam_access.c,v retrieving revision 1.1 retrieving revision 1.8 diff -c -r1.1 -r1.8 *** pam_access.c 2000/11/21 14:50:32 1.1 --- pam_access.c 2000/12/07 19:15:13 1.8 *************** *** 1,17 **** /* 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.) * */ ! #include <features.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> /* man page says above file includes this... */ /* extern int gethostname(char *name, size_t len); */ --- 1,38 ---- /* pam_access module */ ! /* $Id: pam_access.c,v 1.8 2000/12/07 19:15:13 mgerdts Exp $ ! * * 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 + # include <features.h> + #endif /* linux */ + + #ifndef PAM_EXTERN + # define PAM_EXTERN extern + #endif ! #ifndef linux ! # include <unistd.h> ! # include <syslog.h> ! # include <security/pam_appl.h> ! # include <security/pam_modules.h> ! #endif /* ! linux */ ! ! #ifdef hpux ! # include <sys/param.h> ! #endif ! #include <stdio.h> #include <stdlib.h> #include <unistd.h> + static char SCCSiD[] = "@(#)pam_access.c from hacked Red Hat 7 pam-0.72-26.src.rpm"; + /* man page says above file includes this... */ /* extern int gethostname(char *name, size_t len); */ *************** *** 44,52 **** #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, ... ) --- 65,125 ---- #define PAM_SM_ACCOUNT ! #ifdef linux ! # include <security/_pam_macros.h> ! # include <security/pam_modules.h> ! #endif /* linux */ ! ! # ifdef hpux ! extern int innetgr(char *netgroup, char *machine, char *user, char *domain); ! # endif /* hpux */ ! ! /* To use this section, compile with -Dvsyslog=myvsyslog */ ! ! #ifdef vsyslog ! ! /* This section of code is for those OS's (HP-UX) that don't have vsyslog. ! Code stolen from tcp_wrappers 7.6 */ ! ! # ifndef lint ! static char sccsid[] = "@(#) Code stolen from tcp_wrappers myvsyslog.c 1.1 94/12/28 17:42:33"; ! # endif /* lint */ ! ! extern int sys_nerr; ! extern char *sys_errlist[]; ! ! static char *percent_m(char *obuf, char *ibuf) ! { ! char *bp = obuf; ! char *cp = ibuf; + while ((*bp = *cp) != NULL ) + if (*cp == '%' && cp[1] == 'm') { + if (errno < sys_nerr && errno > 0) { + strcpy(bp, sys_errlist[errno]); + } else { + sprintf(bp, "Unknown error %d", errno); + } + bp += strlen(bp); + cp += 2; + } else { + bp++, cp++; + } + return (obuf); + } + + static void myvsyslog(int severity, char *format, va_list ap) + { + char fbuf[BUFSIZ]; + char obuf[BUFSIZ +1]; + + vsnprintf(obuf, BUFSIZ, percent_m(fbuf, format), ap); + obuf[BUFSIZ] = '\0'; + syslog(severity, "%s", obuf); + } + + #endif + /* --- static functions for checking whether the user should be let in --- */ static void _log_err(const char *format, ... ) *************** *** 60,65 **** --- 133,164 ---- closelog(); } + static void _logmail(const char *user, const char *from) { + FILE *sendmail; + char host[MAXHOSTNAMELEN+1]; + + sendmail = popen("/usr/lib/sendmail -t", "w"); + if ( sendmail == NULL ) { + _log_err("cannot send mail: /usr/lib/sendmail -t: %m"); + return; + } + + if ( gethostname(host, MAXHOSTNAMELEN) == -1 ) { + strncpy(host, "UNKNOWN_HOST", MAXHOSTNAMELEN); + } + host[MAXHOSTNAMELEN] = '\0'; + + fprintf(sendmail, "To: %s\n", LOGMAIL_TO); + fprintf(sendmail, "From: %s\n", LOGMAIL_FROM); + fprintf(sendmail, "Subject: %s LOGIN REFUSED on %s from %s\n", + user, host, from); + fprintf(sendmail, "X-Mailer: $Id: pam_access.c,v 1.8 2000/12/07 19:15:13 mgerdts Exp $"); + fprintf(sendmail, "\n"); + fprintf(sendmail, "%s LOGIN REFUSED on %s from %s\n", + user, host, from); + pclose(sendmail); + } + #define PAM_ACCESS_CONFIG CONFILE int strcasecmp(const char *s1, const char *s2); *************** *** 357,363 **** 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; --- 456,462 ---- PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc ,const char **argv) { ! char *user=NULL; char *from=NULL; struct passwd *user_pw; *************** *** 371,389 **** /* 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"); --- 470,488 ---- /* 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 || from[0]=='\0') { /* local login, set tty name */ if (pam_get_item(pamh, PAM_TTY, (const void **)&from) != PAM_SUCCESS || from == NULL) { ! _log_err("PAM_TTY not set, probing stdin"); from = ttyname(STDIN_FILENO); if (from == NULL) { _log_err("couldn't get the tty name"); *************** *** 402,407 **** --- 501,507 ---- 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); + _logmail(user, from); return (PAM_PERM_DENIED); } } *************** *** 423,425 **** --- 523,528 ---- }; #endif + /* + vim: ts=8 sw=8 + */