Added mblogin program
This commit is contained in:
parent
8af5b1c2d1
commit
182f8c6b56
83
config.h.in
83
config.h.in
@ -42,6 +42,7 @@
|
|||||||
#undef REGEX
|
#undef REGEX
|
||||||
#undef REGEXEC
|
#undef REGEXEC
|
||||||
#undef SHADOW_PASSWORD
|
#undef SHADOW_PASSWORD
|
||||||
|
#undef HAVE_SHADOWGRP
|
||||||
#undef SO_OOBINLINE
|
#undef SO_OOBINLINE
|
||||||
|
|
||||||
/* mbuseradd */
|
/* mbuseradd */
|
||||||
@ -51,15 +52,77 @@
|
|||||||
#undef AUTH_METHODS
|
#undef AUTH_METHODS
|
||||||
#undef CKDEFS
|
#undef CKDEFS
|
||||||
#undef DOUBLESIZE
|
#undef DOUBLESIZE
|
||||||
|
|
||||||
|
/* Defined if you have libcrack. */
|
||||||
#undef HAVE_LIBCRACK
|
#undef HAVE_LIBCRACK
|
||||||
|
|
||||||
|
/* Defined if you have the ts&szs cracklib. */
|
||||||
#undef HAVE_LIBCRACK_HIST
|
#undef HAVE_LIBCRACK_HIST
|
||||||
|
|
||||||
|
/* Defined if it includes *Pw functions. */
|
||||||
|
#undef HAVE_LIBCRACK_PW
|
||||||
|
|
||||||
|
|
||||||
|
/* Defined if it includes *Pw functions. */
|
||||||
|
#undef HAVE_LIBCRACK_PW
|
||||||
|
|
||||||
|
/* Defined if you have libcrypt. */
|
||||||
|
#undef HAVE_LIBCRYPT
|
||||||
|
|
||||||
#undef KEEP_NIS_AT_END
|
#undef KEEP_NIS_AT_END
|
||||||
|
|
||||||
|
/* Define to support the MD5-based password hashing algorithm. */
|
||||||
#undef MD5_CRYPT
|
#undef MD5_CRYPT
|
||||||
#undef PAM
|
#undef PAM
|
||||||
|
|
||||||
|
/* Define to support OPIE one-time password logins. */
|
||||||
|
#undef OPIE
|
||||||
#undef SW_CRYPT
|
#undef SW_CRYPT
|
||||||
|
|
||||||
|
/* Define to 1 if NLS is requested. */
|
||||||
|
#undef ENABLE_NLS
|
||||||
|
|
||||||
/* That's it */
|
/* Path for faillog file. */
|
||||||
|
#undef FAILLOG_FILE
|
||||||
|
|
||||||
|
/* Define to libshadow_getpass to use our own version of getpass(). */
|
||||||
|
#undef getpass
|
||||||
|
|
||||||
|
/* Define if your locale.h file contains LC_MESSAGES. */
|
||||||
|
#undef HAVE_LC_MESSAGES
|
||||||
|
|
||||||
|
/* Path for lastlog file. */
|
||||||
|
#undef LASTLOG_FILE
|
||||||
|
|
||||||
|
/* Define to support /etc/login.access login access control. */
|
||||||
|
#undef LOGIN_ACCESS
|
||||||
|
|
||||||
|
/* Path for wtmp file. */
|
||||||
|
#undef _WTMP_FILE
|
||||||
|
|
||||||
|
/* Define if you have the updwtmp function. */
|
||||||
|
#undef HAVE_UPDWTMP
|
||||||
|
|
||||||
|
/* Define if you have the updwtmpx function. */
|
||||||
|
#undef HAVE_UPDWTMPX
|
||||||
|
|
||||||
|
/* Define if mblogin should support the -r flag for rlogind. */
|
||||||
|
#undef RLOGIN
|
||||||
|
|
||||||
|
/* Define if you have the getusershell function. */
|
||||||
|
#undef HAVE_GETUSERSHELL
|
||||||
|
|
||||||
|
/* Define if you have the getutent function. */
|
||||||
|
#undef HAVE_GETUTENT
|
||||||
|
|
||||||
|
/* Define if you have the <lastlog.h> header file. */
|
||||||
|
#undef HAVE_LASTLOG_H
|
||||||
|
|
||||||
|
/* Define if you have ut_host in struct utmp. */
|
||||||
|
#undef UT_HOST
|
||||||
|
|
||||||
|
/* Path for utmp file. */
|
||||||
|
#undef _UTMP_FILE
|
||||||
|
|
||||||
/* Define if you have the `a64l' function. */
|
/* Define if you have the `a64l' function. */
|
||||||
#undef HAVE_A64L
|
#undef HAVE_A64L
|
||||||
@ -142,6 +205,12 @@
|
|||||||
/* Define if you have the `putpwent' function. */
|
/* Define if you have the `putpwent' function. */
|
||||||
#undef HAVE_PUTPWENT
|
#undef HAVE_PUTPWENT
|
||||||
|
|
||||||
|
/* Define if you have the putspent function. */
|
||||||
|
#undef HAVE_PUTSPENT
|
||||||
|
|
||||||
|
/* Define if you have the putgrent function. */
|
||||||
|
#undef HAVE_PUTGRENT
|
||||||
|
|
||||||
/* Define if you have the `regcmp' function. */
|
/* Define if you have the `regcmp' function. */
|
||||||
#undef HAVE_REGCMP
|
#undef HAVE_REGCMP
|
||||||
|
|
||||||
@ -215,6 +284,9 @@
|
|||||||
/* Define if you have the <syslog.h> header file. */
|
/* Define if you have the <syslog.h> header file. */
|
||||||
#undef HAVE_SYSLOG_H
|
#undef HAVE_SYSLOG_H
|
||||||
|
|
||||||
|
/* Define to use syslog(). */
|
||||||
|
#undef USE_SYSLOG
|
||||||
|
|
||||||
/* Define if you have the <sys/dir.h> header file, and it defines `DIR'. */
|
/* Define if you have the <sys/dir.h> header file, and it defines `DIR'. */
|
||||||
#undef HAVE_SYS_DIR_H
|
#undef HAVE_SYS_DIR_H
|
||||||
|
|
||||||
@ -274,6 +346,12 @@
|
|||||||
/* Define if you have the `vprintf' function. */
|
/* Define if you have the `vprintf' function. */
|
||||||
#undef HAVE_VPRINTF
|
#undef HAVE_VPRINTF
|
||||||
|
|
||||||
|
/* Define if you have the memcpy function. */
|
||||||
|
#undef HAVE_MEMCPY
|
||||||
|
|
||||||
|
/* Define if you have the memset function. */
|
||||||
|
#undef HAVE_MEMSET
|
||||||
|
|
||||||
/* Name of package */
|
/* Name of package */
|
||||||
#undef PACKAGE
|
#undef PACKAGE
|
||||||
|
|
||||||
@ -295,8 +373,7 @@
|
|||||||
/* Define if your <sys/time.h> declares `struct tm'. */
|
/* Define if your <sys/time.h> declares `struct tm'. */
|
||||||
#undef TM_IN_SYS_TIME
|
#undef TM_IN_SYS_TIME
|
||||||
|
|
||||||
/* Define if `lex' declares `yytext' as a `char *' by default, not a `char[]'.
|
/* Define if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */
|
||||||
*/
|
|
||||||
#undef YYTEXT_POINTER
|
#undef YYTEXT_POINTER
|
||||||
|
|
||||||
/* Define to empty if `const' does not conform to ANSI C. */
|
/* Define to empty if `const' does not conform to ANSI C. */
|
||||||
|
26
configure.in
26
configure.in
@ -119,6 +119,7 @@ AC_HEADER_TIME
|
|||||||
AC_HEADER_SYS_WAIT
|
AC_HEADER_SYS_WAIT
|
||||||
AC_CHECK_HEADERS(fcntl.h malloc.h sys/file.h sys/ioctl.h sys/time.h termios.h syslog.h sys/vfs.h unistd.h netinet/in.h regex.h)
|
AC_CHECK_HEADERS(fcntl.h malloc.h sys/file.h sys/ioctl.h sys/time.h termios.h syslog.h sys/vfs.h unistd.h netinet/in.h regex.h)
|
||||||
AC_CHECK_HEADERS(sys/resource.h usersec.h utime.h ulimit.h gshadow.h shadow.h)
|
AC_CHECK_HEADERS(sys/resource.h usersec.h utime.h ulimit.h gshadow.h shadow.h)
|
||||||
|
AC_CHECK_HEADERS(limits.h utmp.h utmpx.h sgtty.h lastlog.h rpc/key_prot.h)
|
||||||
AC_STRUCT_TIMEZONE
|
AC_STRUCT_TIMEZONE
|
||||||
|
|
||||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||||
@ -144,6 +145,7 @@ AC_FUNC_UTIME_NULL
|
|||||||
AC_FUNC_VFORK
|
AC_FUNC_VFORK
|
||||||
AC_FUNC_VPRINTF
|
AC_FUNC_VPRINTF
|
||||||
AC_CHECK_FUNCS(getcwd gethostname gettimeofday getwd mkdir mktime putenv re_comp regcmp regcomp rmdir select socket strcspn strdup strerror strspn strstr strtol strtoul uname)
|
AC_CHECK_FUNCS(getcwd gethostname gettimeofday getwd mkdir mktime putenv re_comp regcmp regcomp rmdir select socket strcspn strdup strerror strspn strstr strtol strtoul uname)
|
||||||
|
AC_CHECK_FUNCS(getgroups getspnam getusershell getutent initgroups setgroups updwtmp updwtmpx)
|
||||||
|
|
||||||
dnl Check for external programs
|
dnl Check for external programs
|
||||||
AC_PATH_PROG(COMPRESS,compress,no-compress-found-during-configure)
|
AC_PATH_PROG(COMPRESS,compress,no-compress-found-during-configure)
|
||||||
@ -165,6 +167,30 @@ AC_SUBST(LOG_COMPRESS)
|
|||||||
AC_SUBST(LOG_COMPRESSEXT)
|
AC_SUBST(LOG_COMPRESSEXT)
|
||||||
dnl
|
dnl
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(location of utmp)
|
||||||
|
for utmpdir in /var/run /var/adm /usr/adm /etc NONE; do
|
||||||
|
if test "$utmpdir" = "NONE"; then
|
||||||
|
AC_MSG_WARN(utmp file not found)
|
||||||
|
elif test -f $utmpdir/utmp; then
|
||||||
|
AC_DEFINE_UNQUOTED(_UTMP_FILE, "$utmpdir/utmp")
|
||||||
|
AC_MSG_RESULT($utmpdir)
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(location of faillog/lastlog/wtmp)
|
||||||
|
for logdir in /var/log /var/adm /usr/adm /etc; do
|
||||||
|
if test -d $logdir; then
|
||||||
|
AC_DEFINE_UNQUOTED(_WTMP_FILE, "$logdir/wtmp")
|
||||||
|
AC_DEFINE_UNQUOTED(LASTLOG_FILE, "$logdir/lastlog")
|
||||||
|
AC_DEFINE_UNQUOTED(FAILLOG_FILE, "$logdir/faillog")
|
||||||
|
AC_MSG_RESULT($logdir)
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AC_OUTPUT(
|
AC_OUTPUT(
|
||||||
Makefile.global
|
Makefile.global
|
||||||
mbfido/paths.h
|
mbfido/paths.h
|
||||||
|
@ -12,7 +12,10 @@ SRCS = bank.c commonio.c filesub.c language.c mbtoberep.c \
|
|||||||
exitinfo.c mball.c mbsebbs.c menu.c nextuser.c pop3.c lastcallers.c \
|
exitinfo.c mball.c mbsebbs.c menu.c nextuser.c pop3.c lastcallers.c \
|
||||||
safe.c timeout.c chat.c file.c getdef.c mbchat.c mbstat.c misc.c \
|
safe.c timeout.c chat.c file.c getdef.c mbchat.c mbstat.c misc.c \
|
||||||
offline.c putpwent.c salt.c user.c mbnewusr.c input.c whoson.c \
|
offline.c putpwent.c salt.c user.c mbnewusr.c input.c whoson.c \
|
||||||
door.c dispfile.c userlist.c timestats.c logentry.c pw_util.c
|
door.c dispfile.c userlist.c timestats.c logentry.c pw_util.c \
|
||||||
|
mblogin.c env.c snprintf.c chowntty.c ttytype.c shell.c basename.c \
|
||||||
|
failure.c pwdcheck.c pwauth.c loginprompt.c utmp.c limits.c \
|
||||||
|
setupenv.c sub.c ulimit.c log.c tz.c setugid.c
|
||||||
HDRS = bank.h commonio.h filesub.h language.h mbsebbs.h misc.h offline.h \
|
HDRS = bank.h commonio.h filesub.h language.h mbsebbs.h misc.h offline.h \
|
||||||
putpwent.h salt.h timeout.h bbslist.h email.h fsedit.h lineedit.h \
|
putpwent.h salt.h timeout.h bbslist.h email.h fsedit.h lineedit.h \
|
||||||
mbstat.h msgutil.h oneline.h sgetpwent.h user.h bye.h morefile.h \
|
mbstat.h msgutil.h oneline.h sgetpwent.h user.h bye.h morefile.h \
|
||||||
@ -20,7 +23,10 @@ HDRS = bank.h commonio.h filesub.h language.h mbsebbs.h misc.h offline.h \
|
|||||||
xmalloc.h change.h exitinfo.h mball.h mbuseradd.h newuser.h \
|
xmalloc.h change.h exitinfo.h mball.h mbuseradd.h newuser.h \
|
||||||
pinfo.h rad64.h chat.h file.h getdef.h mbpasswd.h menu.h \
|
pinfo.h rad64.h chat.h file.h getdef.h mbpasswd.h menu.h \
|
||||||
nextuser.h pop3.h safe.h timecheck.h mbnewusr.h input.h whoson.h \
|
nextuser.h pop3.h safe.h timecheck.h mbnewusr.h input.h whoson.h \
|
||||||
door.h dispfile.h userlist.h timestats.h logentry.h lastcallers.h pw_util.h
|
door.h dispfile.h userlist.h timestats.h logentry.h lastcallers.h pw_util.h \
|
||||||
|
mblogin.h env.h snprintf.h chowntty.h ttytype.h shell.h basename.h \
|
||||||
|
failure.h pwdcheck.h pwauth.h loginprompt.h utmp.h limits.h \
|
||||||
|
setupenv.h sub.h ulimit.h log.h tz.h setugid.h
|
||||||
MBSEBBS_OBJS = bank.o bbslist.o chat.o file.o funcs.o mail.o menu.o \
|
MBSEBBS_OBJS = bank.o bbslist.o chat.o file.o funcs.o mail.o menu.o \
|
||||||
misc.o pinfo.o nextuser.o oneline.o page.o fsedit.o \
|
misc.o pinfo.o nextuser.o oneline.o page.o fsedit.o \
|
||||||
bye.o change.o mbsebbs.o safe.o timeout.o user.o timecheck.o \
|
bye.o change.o mbsebbs.o safe.o timeout.o user.o timecheck.o \
|
||||||
@ -49,8 +55,11 @@ MBUSER_LIBS = ../lib/libmemwatch.a ../lib/libclcomm.a ../lib/libcommon.a ../lib/
|
|||||||
MBUSERADD_OBJS = mbuseradd.o
|
MBUSERADD_OBJS = mbuseradd.o
|
||||||
MBPASSWD_OBJS = mbpasswd.o commonio.o pwio.o shadowio.o sgetpwent.o \
|
MBPASSWD_OBJS = mbpasswd.o commonio.o pwio.o shadowio.o sgetpwent.o \
|
||||||
xmalloc.o myname.o rad64.o salt.o getdef.o encrypt.o putpwent.o pw_util.o
|
xmalloc.o myname.o rad64.o salt.o getdef.o encrypt.o putpwent.o pw_util.o
|
||||||
|
MBLOGIN_OBJS = getdef.o env.o snprintf.o chowntty.o ttytype.o shell.o basename.o failure.o \
|
||||||
|
pwdcheck.o pwauth.o encrypt.o loginprompt.o utmp.o limits.o setupenv.o sub.o \
|
||||||
|
xmalloc.o ulimit.o log.o tz.o setugid.o mblogin.o
|
||||||
OTHER = Makefile
|
OTHER = Makefile
|
||||||
TARGET = mbsebbs mbnewusr mball mblang mbchat mbstat mbtoberep mbuser mbuseradd mbpasswd
|
TARGET = mbsebbs mbnewusr mball mblang mbchat mbstat mbtoberep mbuser mbuseradd mbpasswd mblogin
|
||||||
|
|
||||||
#############################################################################################################
|
#############################################################################################################
|
||||||
|
|
||||||
@ -102,6 +111,10 @@ mbpasswd: ${MBPASSWD_OBJS}
|
|||||||
${CC} -o mbpasswd ${MBPASSWD_OBJS} ${LIBS}
|
${CC} -o mbpasswd ${MBPASSWD_OBJS} ${LIBS}
|
||||||
strip mbpasswd
|
strip mbpasswd
|
||||||
|
|
||||||
|
mblogin: ${MBLOGIN_OBJS}
|
||||||
|
${CC} -o mblogin ${MBLOGIN_OBJS} ${LIBS}
|
||||||
|
strip mblogin
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
@if [ "`id -un`" != "root" ] ; then \
|
@if [ "`id -un`" != "root" ] ; then \
|
||||||
echo; echo " Must be root to install!"; echo; exit 3; \
|
echo; echo " Must be root to install!"; echo; exit 3; \
|
||||||
@ -116,6 +129,7 @@ install: all
|
|||||||
${INSTALL} -c -s -o `id -un` -g `id -gn` -m 6711 mbuser ${BINDIR}
|
${INSTALL} -c -s -o `id -un` -g `id -gn` -m 6711 mbuser ${BINDIR}
|
||||||
${INSTALL} -c -s -o `id -un` -g `id -gn` -m 6711 mbuseradd ${BINDIR}
|
${INSTALL} -c -s -o `id -un` -g `id -gn` -m 6711 mbuseradd ${BINDIR}
|
||||||
${INSTALL} -c -s -o `id -un` -g `id -gn` -m 6711 mbpasswd ${BINDIR}
|
${INSTALL} -c -s -o `id -un` -g `id -gn` -m 6711 mbpasswd ${BINDIR}
|
||||||
|
${INSTALL} -c -s -o `id -un` -g `id -gn` -m 0755 mblogin ${BINDIR}
|
||||||
@rm -f ${BINDIR}/mbfbgen
|
@rm -f ${BINDIR}/mbfbgen
|
||||||
|
|
||||||
filelist: Makefile
|
filelist: Makefile
|
||||||
@ -206,4 +220,23 @@ userlist.o: ../lib/libs.h ../lib/mbse.h ../lib/structs.h ../lib/records.h ../lib
|
|||||||
timestats.o: ../lib/libs.h ../lib/mbse.h ../lib/structs.h ../lib/records.h ../lib/common.h timestats.h funcs.h language.h input.h exitinfo.h
|
timestats.o: ../lib/libs.h ../lib/mbse.h ../lib/structs.h ../lib/records.h ../lib/common.h timestats.h funcs.h language.h input.h exitinfo.h
|
||||||
logentry.o: ../lib/libs.h ../lib/mbse.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h logentry.h
|
logentry.o: ../lib/libs.h ../lib/mbse.h ../lib/structs.h ../lib/records.h ../lib/common.h ../lib/clcomm.h logentry.h
|
||||||
pw_util.o: pw_util.h
|
pw_util.o: pw_util.h
|
||||||
|
mblogin.o: ../config.h mblogin.h getdef.h env.h chowntty.h ttytype.h basename.h shell.h failure.h pwdcheck.h pwauth.h loginprompt.h utmp.h limits.h setupenv.h sub.h ulimit.h log.h tz.h setugid.h
|
||||||
|
env.o: ../config.h mblogin.h xmalloc.h
|
||||||
|
snprintf.o: snprintf.h
|
||||||
|
chowntty.o: ../config.h mblogin.h getdef.h chowntty.h
|
||||||
|
ttytype.o: ../config.h mblogin.h getdef.h env.h ttytype.h
|
||||||
|
shell.o: ../config.h mblogin.h basename.h shell.h
|
||||||
|
basename.o: ../config.h mblogin.h basename.h
|
||||||
|
failure.o: ../config.h mblogin.h getdef.h failure.h
|
||||||
|
pwdcheck.o: ../config.h mblogin.h pwauth.h pwdcheck.h
|
||||||
|
pwauth.o: ../config.h mblogin.h pwauth.h getdef.h encrypt.h
|
||||||
|
loginprompt.o: ../config.h mblogin.h getdef.h xmalloc.h env.h loginprompt.h
|
||||||
|
utmp.o: ../config.h mblogin.h utmp.h
|
||||||
|
limits.o: ../config.h mblogin.h getdef.h utmp.h ulimit.h
|
||||||
|
setupenv.o: ../config.h mblogin.h getdef.h xmalloc.h env.h setupenv.h
|
||||||
|
sub.o: ../config.h mblogin.h sub.h
|
||||||
|
ulimit.o: ../config.h ulimit.h
|
||||||
|
log.o: ../config.h mblogin.h log.h
|
||||||
|
tz.o: ../config.h mblogin.h getdef.h tz.h
|
||||||
|
setugid.o: ../config.h mblogin.h getdef.h setugid.h
|
||||||
# End of generated dependencies
|
# End of generated dependencies
|
||||||
|
17
mbsebbs/basename.c
Normal file
17
mbsebbs/basename.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* basename.c - not worth copyrighting :-). Some versions of Linux libc
|
||||||
|
* already have basename(), other versions don't. To avoid confusion,
|
||||||
|
* we will not use the function from libc and use a different name here.
|
||||||
|
* --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "basename.h"
|
||||||
|
|
||||||
|
char *Basename(char *str)
|
||||||
|
{
|
||||||
|
char *cp = strrchr(str, '/');
|
||||||
|
|
||||||
|
return cp ? cp+1 : str;
|
||||||
|
}
|
9
mbsebbs/basename.h
Normal file
9
mbsebbs/basename.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _BASENAME_H
|
||||||
|
#define _BASENAME_H
|
||||||
|
|
||||||
|
|
||||||
|
char *Basename(char *);
|
||||||
|
|
||||||
|
#endif
|
123
mbsebbs/chowntty.c
Normal file
123
mbsebbs/chowntty.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <grp.h>
|
||||||
|
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <pwd.h>
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "chowntty.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* is_my_tty -- determine if "tty" is the same as TTY stdin is using
|
||||||
|
*/
|
||||||
|
|
||||||
|
int is_my_tty(const char *tty)
|
||||||
|
{
|
||||||
|
struct stat by_name, by_fd;
|
||||||
|
|
||||||
|
if (stat (tty, &by_name) || fstat (0, &by_fd))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (by_name.st_rdev != by_fd.st_rdev)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* chown_tty() sets the login tty to be owned by the new user ID
|
||||||
|
* with TTYPERM modes
|
||||||
|
*/
|
||||||
|
|
||||||
|
void chown_tty(const char *tty, const struct passwd *info)
|
||||||
|
{
|
||||||
|
char buf[200], full_tty[200];
|
||||||
|
char *group; /* TTY group name or number */
|
||||||
|
struct group *grent;
|
||||||
|
gid_t gid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if login.defs has some value configured for the port group
|
||||||
|
* ID. Otherwise, use the user's primary group ID.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (! (group = getdef_str ("TTYGROUP")))
|
||||||
|
gid = info->pw_gid;
|
||||||
|
else if (group[0] >= '0' && group[0] <= '9')
|
||||||
|
gid = atoi (group);
|
||||||
|
else if ((grent = getgrnam (group)))
|
||||||
|
gid = grent->gr_gid;
|
||||||
|
else
|
||||||
|
gid = info->pw_gid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change the permissions on the TTY to be owned by the user with
|
||||||
|
* the group as determined above.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (*tty != '/') {
|
||||||
|
snprintf(full_tty, sizeof full_tty, "/dev/%s", tty);
|
||||||
|
tty = full_tty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! is_my_tty (tty)) {
|
||||||
|
syslog(LOG_WARNING, "unable to determine TTY name, got %s\n", tty);
|
||||||
|
closelog();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chown(tty, info->pw_uid, gid) || chmod(tty, getdef_num("TTYPERM", 0600))) {
|
||||||
|
snprintf(buf, sizeof buf, "Unable to change tty %s", tty);
|
||||||
|
syslog(LOG_WARNING, "unable to change tty `%s' for user `%s'\n", tty, info->pw_name);
|
||||||
|
closelog();
|
||||||
|
perror (buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
/*
|
||||||
|
* Please don't add code to chown /dev/vcs* to the user logging in -
|
||||||
|
* it's a potential security hole. I wouldn't like the previous user
|
||||||
|
* to hold the file descriptor open and watch my screen. We don't
|
||||||
|
* have the *BSD revoke() system call yet, and vhangup() only works
|
||||||
|
* for tty devices (which vcs* is not). --marekm
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
}
|
11
mbsebbs/chowntty.h
Normal file
11
mbsebbs/chowntty.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _CHOWNTTY_H
|
||||||
|
#define _CHOWNTTY_H
|
||||||
|
|
||||||
|
|
||||||
|
int is_my_tty(const char *);
|
||||||
|
void chown_tty(const char *, const struct passwd *);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -1,10 +1,9 @@
|
|||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* File ..................: mbuseradd/encrypt.c
|
* $Id$
|
||||||
* Purpose ...............: MBSE BBS Shadow Password Suite
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
* Last modification date : 09-Aug-2001
|
|
||||||
* Original Source .......: Shadow Password Suite
|
* Original Source .......: Shadow Password Suite
|
||||||
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
*
|
*
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
* Copyright (C) 1997-2001
|
* Copyright (C) 1997-2001
|
||||||
@ -146,6 +145,10 @@ char *pw_encrypt(const char *clear, const char *salt)
|
|||||||
#ifdef DOUBLESIZE
|
#ifdef DOUBLESIZE
|
||||||
if (strlen (clear) > 8) {
|
if (strlen (clear) > 8) {
|
||||||
cp = crypt (clear + 8, salt);
|
cp = crypt (clear + 8, salt);
|
||||||
|
if (!cp) {
|
||||||
|
perror("crypt");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
strcat (cipher, cp + 2);
|
strcat (cipher, cp + 2);
|
||||||
}
|
}
|
||||||
#endif /* DOUBLESIZE */
|
#endif /* DOUBLESIZE */
|
||||||
|
253
mbsebbs/env.c
Normal file
253
mbsebbs/env.c
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NEWENVP_STEP must be a power of two. This is the number
|
||||||
|
* of (char *) pointers to allocate at a time, to avoid using
|
||||||
|
* realloc() too often.
|
||||||
|
*/
|
||||||
|
#define NEWENVP_STEP 16
|
||||||
|
|
||||||
|
size_t newenvc = 0;
|
||||||
|
char **newenvp = NULL;
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
|
||||||
|
static const char *forbid[] = {
|
||||||
|
"_RLD_=",
|
||||||
|
"BASH_ENV=", /* GNU creeping featurism strikes again... */
|
||||||
|
"ENV=",
|
||||||
|
"HOME=",
|
||||||
|
"IFS=",
|
||||||
|
"KRB_CONF=",
|
||||||
|
"LD_", /* anything with the LD_ prefix */
|
||||||
|
"LIBPATH=",
|
||||||
|
"MAIL=",
|
||||||
|
"NLSPATH=",
|
||||||
|
"PATH=",
|
||||||
|
"SHELL=",
|
||||||
|
"SHLIB_PATH=",
|
||||||
|
(char *) 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* these are allowed, but with no slashes inside
|
||||||
|
(to work around security problems in GNU gettext) */
|
||||||
|
static const char *noslash[] = {
|
||||||
|
"LANG=",
|
||||||
|
"LANGUAGE=",
|
||||||
|
"LC_", /* anything with the LC_ prefix */
|
||||||
|
(char *) 0
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initenv() must be called once before using addenv().
|
||||||
|
*/
|
||||||
|
void initenv(void)
|
||||||
|
{
|
||||||
|
newenvp = (char **)xmalloc(NEWENVP_STEP * sizeof(char *));
|
||||||
|
*newenvp = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void addenv(const char *string, const char *value)
|
||||||
|
{
|
||||||
|
char *cp, *newstring;
|
||||||
|
size_t i;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
newstring = xmalloc(strlen(string) + strlen(value) + 2);
|
||||||
|
sprintf(newstring, "%s=%s", string, value);
|
||||||
|
} else {
|
||||||
|
newstring = xstrdup(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Search for a '=' character within the string and if none is found
|
||||||
|
* just ignore the whole string.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cp = strchr(newstring, '=');
|
||||||
|
if (!cp) {
|
||||||
|
free(newstring);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = (size_t)(cp - newstring);
|
||||||
|
|
||||||
|
for (i = 0; i < newenvc; i++) {
|
||||||
|
if (strncmp(newstring, newenvp[i], n) == 0 &&
|
||||||
|
(newenvp[i][n] == '=' || newenvp[i][n] == '\0'))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < newenvc) {
|
||||||
|
free(newenvp[i]);
|
||||||
|
newenvp[i] = newstring;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
newenvp[newenvc++] = newstring;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether newenvc is a multiple of NEWENVP_STEP.
|
||||||
|
* If so we have to resize the vector.
|
||||||
|
* the expression (newenvc & (NEWENVP_STEP - 1)) == 0
|
||||||
|
* is equal to (newenvc % NEWENVP_STEP) == 0
|
||||||
|
* as long as NEWENVP_STEP is a power of 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((newenvc & (NEWENVP_STEP - 1)) == 0) {
|
||||||
|
char **__newenvp;
|
||||||
|
size_t newsize;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the resize operation succeds we can
|
||||||
|
* happily go on, else print a message.
|
||||||
|
*/
|
||||||
|
|
||||||
|
newsize = (newenvc + NEWENVP_STEP) * sizeof(char *);
|
||||||
|
__newenvp = (char **)realloc(newenvp, newsize);
|
||||||
|
|
||||||
|
if (__newenvp) {
|
||||||
|
/*
|
||||||
|
* If this is our current environment, update
|
||||||
|
* environ so that it doesn't point to some
|
||||||
|
* free memory area (realloc() could move it).
|
||||||
|
*/
|
||||||
|
if (environ == newenvp)
|
||||||
|
environ = __newenvp;
|
||||||
|
newenvp = __newenvp;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Environment overflow\n");
|
||||||
|
free(newenvp[--newenvc]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The last entry of newenvp must be NULL
|
||||||
|
*/
|
||||||
|
|
||||||
|
newenvp[newenvc] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set_env - copy command line arguments into the environment
|
||||||
|
*/
|
||||||
|
void set_env(int argc, char * const *argv)
|
||||||
|
{
|
||||||
|
int noname = 1;
|
||||||
|
char variable[1024];
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
for ( ; argc > 0; argc--, argv++) {
|
||||||
|
if (strlen(*argv) >= sizeof variable)
|
||||||
|
continue; /* ignore long entries */
|
||||||
|
|
||||||
|
if (! (cp = strchr (*argv, '='))) {
|
||||||
|
snprintf(variable, sizeof variable, "L%d", noname++);
|
||||||
|
addenv(variable, *argv);
|
||||||
|
} else {
|
||||||
|
const char **p;
|
||||||
|
|
||||||
|
for (p = forbid; *p; p++)
|
||||||
|
if (strncmp(*argv, *p, strlen(*p)) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*p) {
|
||||||
|
strncpy(variable, *argv, cp - *argv);
|
||||||
|
variable[cp - *argv] = '\0';
|
||||||
|
printf("You may not change $%s\n", variable);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
addenv(*argv, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sanitize_env - remove some nasty environment variables
|
||||||
|
* If you fall into a total paranoia, you should call this
|
||||||
|
* function for any root-setuid program or anything the user
|
||||||
|
* might change the environment with. 99% useless as almost
|
||||||
|
* all modern Unixes will handle setuid executables properly,
|
||||||
|
* but... I feel better with that silly precaution. -j.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void sanitize_env(void)
|
||||||
|
{
|
||||||
|
char **envp = environ;
|
||||||
|
const char **bad;
|
||||||
|
char **cur;
|
||||||
|
char **move;
|
||||||
|
|
||||||
|
for (cur = envp; *cur; cur++) {
|
||||||
|
for (bad = forbid; *bad; bad++) {
|
||||||
|
if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
|
||||||
|
for (move = cur; *move; move++)
|
||||||
|
*move = *(move + 1);
|
||||||
|
cur--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (cur = envp; *cur; cur++) {
|
||||||
|
for (bad = noslash; *bad; bad++) {
|
||||||
|
if (strncmp(*cur, *bad, strlen(*bad)) != 0)
|
||||||
|
continue;
|
||||||
|
if (!strchr(*cur, '/'))
|
||||||
|
continue; /* OK */
|
||||||
|
for (move = cur; *move; move++)
|
||||||
|
*move = *(move + 1);
|
||||||
|
cur--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
12
mbsebbs/env.h
Normal file
12
mbsebbs/env.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _ENV_H
|
||||||
|
#define _ENV_H
|
||||||
|
|
||||||
|
void initenv(void);
|
||||||
|
void addenv(const char *, const char *);
|
||||||
|
void set_env(int, char * const *);
|
||||||
|
void sanitize_env(void);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
273
mbsebbs/failure.c
Normal file
273
mbsebbs/failure.c
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "getdef.h"
|
||||||
|
#include <utmp.h>
|
||||||
|
#include "failure.h"
|
||||||
|
|
||||||
|
#define YEAR (365L*DAY)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* failure - make failure entry
|
||||||
|
*
|
||||||
|
* failure() creates a new (struct faillog) entry or updates an
|
||||||
|
* existing one with the current failed login information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void failure(uid_t uid, const char *tty, struct faillog *fl)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't do anything if failure logging isn't set up.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((fd = open(FAILLOG_FILE, O_RDWR)) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The file is indexed by uid value meaning that shared UID's
|
||||||
|
* share failure log records. That's OK since they really
|
||||||
|
* share just about everything else ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
lseek(fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
|
||||||
|
if (read(fd, (char *) fl, sizeof *fl) != sizeof *fl)
|
||||||
|
memzero(fl, sizeof *fl);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the record. We increment the failure count to log the
|
||||||
|
* latest failure. The only concern here is overflow, and we'll
|
||||||
|
* check for that. The line name and time of day are both
|
||||||
|
* updated as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (fl->fail_cnt + 1 > 0)
|
||||||
|
fl->fail_cnt++;
|
||||||
|
|
||||||
|
strncpy(fl->fail_line, tty, sizeof fl->fail_line);
|
||||||
|
time(&fl->fail_time);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Seek back to the correct position in the file and write the
|
||||||
|
* record out. Ideally we should lock the file in case the same
|
||||||
|
* account is being logged simultaneously. But the risk doesn't
|
||||||
|
* seem that great.
|
||||||
|
*/
|
||||||
|
|
||||||
|
lseek(fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
|
||||||
|
write(fd, (char *) fl, sizeof *fl);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int too_many_failures(const struct faillog *fl)
|
||||||
|
{
|
||||||
|
time_t now;
|
||||||
|
|
||||||
|
if (fl->fail_max == 0 || fl->fail_cnt < fl->fail_max)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (fl->fail_locktime == 0)
|
||||||
|
return 1; /* locked until reset manually */
|
||||||
|
|
||||||
|
time(&now);
|
||||||
|
if (fl->fail_time + fl->fail_locktime > now)
|
||||||
|
return 0; /* enough time since last failure */
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* failcheck - check for failures > allowable
|
||||||
|
*
|
||||||
|
* failcheck() is called AFTER the password has been validated. If the
|
||||||
|
* account has been "attacked" with too many login failures, failcheck()
|
||||||
|
* returns FALSE to indicate that the login should be denied even though
|
||||||
|
* the password is valid.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int failcheck(uid_t uid, struct faillog *fl, int failed)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct faillog fail;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Suppress the check if the log file isn't there.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((fd = open(FAILLOG_FILE, O_RDWR)) < 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the record from the file and determine if the user has
|
||||||
|
* exceeded the failure limit. If "max" is zero, any number
|
||||||
|
* of failures are permitted. Only when "max" is non-zero and
|
||||||
|
* "cnt" is greater than or equal to "max" is the account
|
||||||
|
* considered to be locked.
|
||||||
|
*
|
||||||
|
* If read fails, there is no record for this user yet (the
|
||||||
|
* file is initially zero length and extended by writes), so
|
||||||
|
* no need to reset the count.
|
||||||
|
*/
|
||||||
|
|
||||||
|
lseek (fd, (off_t) (sizeof *fl) * uid, SEEK_SET);
|
||||||
|
if (read(fd, (char *) fl, sizeof *fl) != sizeof *fl) {
|
||||||
|
close(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (too_many_failures(fl)) {
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The record is updated if this is not a failure. The count will
|
||||||
|
* be reset to zero, but the rest of the information will be left
|
||||||
|
* in the record in case someone wants to see where the failed
|
||||||
|
* login originated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!failed) {
|
||||||
|
fail = *fl;
|
||||||
|
fail.fail_cnt = 0;
|
||||||
|
|
||||||
|
lseek (fd, (off_t) sizeof fail * uid, SEEK_SET);
|
||||||
|
write (fd, (char *) &fail, sizeof fail);
|
||||||
|
}
|
||||||
|
close (fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* failprint - print line of failure information
|
||||||
|
*
|
||||||
|
* failprint takes a (struct faillog) entry and formats it into a
|
||||||
|
* message which is displayed at login time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void failprint(const struct faillog *fail)
|
||||||
|
{
|
||||||
|
struct tm *tp;
|
||||||
|
#if HAVE_STRFTIME
|
||||||
|
char lasttimeb[256];
|
||||||
|
char *lasttime = lasttimeb;
|
||||||
|
const char *fmt;
|
||||||
|
#else
|
||||||
|
char *lasttime;
|
||||||
|
#endif
|
||||||
|
time_t NOW;
|
||||||
|
|
||||||
|
if (fail->fail_cnt == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tp = localtime (&(fail->fail_time));
|
||||||
|
time(&NOW);
|
||||||
|
|
||||||
|
#if HAVE_STRFTIME
|
||||||
|
/*
|
||||||
|
* Only print as much date and time info as it needed to
|
||||||
|
* know when the failure was.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (NOW - fail->fail_time >= YEAR)
|
||||||
|
fmt = "%Y";
|
||||||
|
else if (NOW - fail->fail_time >= DAY)
|
||||||
|
fmt = "%A %T";
|
||||||
|
else
|
||||||
|
fmt = "%T";
|
||||||
|
strftime(lasttimeb, sizeof lasttimeb, fmt, tp);
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do the same thing, but don't use strftime since it
|
||||||
|
* probably doesn't exist on this system
|
||||||
|
*/
|
||||||
|
|
||||||
|
lasttime = asctime (tp);
|
||||||
|
lasttime[24] = '\0';
|
||||||
|
|
||||||
|
if (NOW - fail->fail_time < YEAR)
|
||||||
|
lasttime[19] = '\0';
|
||||||
|
if (NOW - fail->fail_time < DAY)
|
||||||
|
lasttime = lasttime + 11;
|
||||||
|
|
||||||
|
if (*lasttime == ' ')
|
||||||
|
lasttime++;
|
||||||
|
#endif
|
||||||
|
printf ("%d %s since last login. Last was %s on %s.\n",
|
||||||
|
fail->fail_cnt, fail->fail_cnt > 1 ? "failures":"failure",
|
||||||
|
lasttime, fail->fail_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* failtmp - update the cummulative failure log
|
||||||
|
*
|
||||||
|
* failtmp updates the (struct utmp) formatted failure log which
|
||||||
|
* maintains a record of all login failures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void failtmp(const struct utmp *failent)
|
||||||
|
{
|
||||||
|
char *ftmp;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the name of the failure file. If no file has been defined
|
||||||
|
* in login.defs, don't do this.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!(ftmp = getdef_str("FTMP_FILE")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the file for append. It must already exist for this
|
||||||
|
* feature to be used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((fd = open(ftmp, O_WRONLY|O_APPEND)) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output the new failure record and close the log file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
write(fd, (const char *) failent, sizeof *failent);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
42
mbsebbs/failure.h
Normal file
42
mbsebbs/failure.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _FAILURE_H_
|
||||||
|
#define _FAILURE_H_
|
||||||
|
|
||||||
|
#include <utmp.h>
|
||||||
|
/*
|
||||||
|
* failure - make failure entry
|
||||||
|
*
|
||||||
|
* failure() creates a new (struct faillog) entry or updates an
|
||||||
|
* existing one with the current failed login information.
|
||||||
|
*/
|
||||||
|
extern void failure(uid_t, const char *, struct faillog *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* failcheck - check for failures > allowable
|
||||||
|
*
|
||||||
|
* failcheck() is called AFTER the password has been validated. If the
|
||||||
|
* account has been "attacked" with too many login failures, failcheck()
|
||||||
|
* returns FALSE to indicate that the login should be denied even though
|
||||||
|
* the password is valid.
|
||||||
|
*/
|
||||||
|
extern int failcheck(uid_t, struct faillog *, int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* failprint - print line of failure information
|
||||||
|
*
|
||||||
|
* failprint takes a (struct faillog) entry and formats it into a
|
||||||
|
* message which is displayed at login time.
|
||||||
|
*/
|
||||||
|
extern void failprint(const struct faillog *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* failtmp - update the cummulative failure log
|
||||||
|
*
|
||||||
|
* failtmp updates the (struct utmp) formatted failure log which
|
||||||
|
* maintains a record of all login failures.
|
||||||
|
*/
|
||||||
|
extern void failtmp(const struct utmp *);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
420
mbsebbs/limits.c
Normal file
420
mbsebbs/limits.c
Normal file
@ -0,0 +1,420 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Separated from setup.c. --marekm
|
||||||
|
* Resource limits thanks to Cristian Gafton.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <utmp.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "utmp.h"
|
||||||
|
#include "ulimit.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_RESOURCE_H
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#define LIMITS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LIMITS
|
||||||
|
|
||||||
|
#ifndef LIMITS_FILE
|
||||||
|
#define LIMITS_FILE "/etc/limits"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOGIN_ERROR_RLIMIT 1
|
||||||
|
#define LOGIN_ERROR_LOGIN 2
|
||||||
|
|
||||||
|
/* Set a limit on a resource */
|
||||||
|
/*
|
||||||
|
* rlimit - RLIMIT_XXXX
|
||||||
|
* value - string value to be read
|
||||||
|
* multiplier - value*multiplier is the actual limit
|
||||||
|
*/
|
||||||
|
int setrlimit_value(unsigned int rlimit, const char *value, unsigned int multiplier)
|
||||||
|
{
|
||||||
|
struct rlimit rlim;
|
||||||
|
long limit;
|
||||||
|
char **endptr = (char **) &value;
|
||||||
|
const char *value_orig = value;
|
||||||
|
|
||||||
|
limit = strtol(value, endptr, 10);
|
||||||
|
if (limit == 0 && value_orig == *endptr) /* no chars read */
|
||||||
|
return 0;
|
||||||
|
limit *= multiplier;
|
||||||
|
rlim.rlim_cur = limit;
|
||||||
|
rlim.rlim_max = limit;
|
||||||
|
if (setrlimit(rlimit, &rlim))
|
||||||
|
return LOGIN_ERROR_RLIMIT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int set_prio(const char *value)
|
||||||
|
{
|
||||||
|
int prio;
|
||||||
|
char **endptr = (char **) &value;
|
||||||
|
|
||||||
|
prio = strtol(value, endptr, 10);
|
||||||
|
if ((prio == 0) && (value == *endptr))
|
||||||
|
return 0;
|
||||||
|
if (setpriority(PRIO_PROCESS, 0, prio))
|
||||||
|
return LOGIN_ERROR_RLIMIT;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int set_umask(const char *value)
|
||||||
|
{
|
||||||
|
mode_t mask;
|
||||||
|
char **endptr = (char **) &value;
|
||||||
|
|
||||||
|
mask = strtol(value, endptr, 8) & 0777;
|
||||||
|
if ((mask == 0) && (value == *endptr))
|
||||||
|
return 0;
|
||||||
|
umask(mask);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Counts the number of user logins and check against the limit */
|
||||||
|
int check_logins(const char *name, const char *maxlogins)
|
||||||
|
{
|
||||||
|
struct utmp *ut;
|
||||||
|
unsigned int limit, count;
|
||||||
|
char **endptr = (char **) &maxlogins;
|
||||||
|
const char *ml_orig = maxlogins;
|
||||||
|
|
||||||
|
limit = strtol(maxlogins, endptr, 10);
|
||||||
|
if (limit == 0 && ml_orig == *endptr) /* no chars read */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (limit == 0) /* maximum 0 logins ? */ {
|
||||||
|
syslog(LOG_WARNING, "No logins allowed for `%s'\n", name);
|
||||||
|
return LOGIN_ERROR_LOGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (strncmp(name, ut->ut_user, sizeof(ut->ut_user)) != 0)
|
||||||
|
continue;
|
||||||
|
if (++count > limit)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
endutent();
|
||||||
|
/*
|
||||||
|
* This is called after setutmp(), so the number of logins counted
|
||||||
|
* includes the user who is currently trying to log in.
|
||||||
|
*/
|
||||||
|
if (count > limit) {
|
||||||
|
syslog(LOG_WARNING, "Too many logins (max %d) for %s\n", limit, name);
|
||||||
|
return LOGIN_ERROR_LOGIN;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function setup_user_limits - checks/set limits for the curent login
|
||||||
|
* Original idea from Joel Katz's lshell. Ported to shadow-login
|
||||||
|
* by Cristian Gafton - gafton@sorosis.ro
|
||||||
|
*
|
||||||
|
* We are passed a string of the form ('BASH' constants for ulimit)
|
||||||
|
* [Aa][Cc][Dd][Ff][Mm][Nn][Rr][Ss][Tt][Uu][Ll][Pp]
|
||||||
|
* (eg. 'C2F256D2048N5' or 'C2 F256 D2048 N5')
|
||||||
|
* where:
|
||||||
|
* [Aa]: a = RLIMIT_AS max address space (KB)
|
||||||
|
* [Cc]: c = RLIMIT_CORE max core file size (KB)
|
||||||
|
* [Dd]: d = RLIMIT_DATA max data size (KB)
|
||||||
|
* [Ff]: f = RLIMIT_FSIZE max file size (KB)
|
||||||
|
* [Mm]: m = RLIMIT_MEMLOCK max locked-in-memory address space (KB)
|
||||||
|
* [Nn]: n = RLIMIT_NOFILE max number of open files
|
||||||
|
* [Rr]: r = RLIMIT_RSS max resident set size (KB)
|
||||||
|
* [Ss]: s = RLIMIT_STACK max stack size (KB)
|
||||||
|
* [Tt]: t = RLIMIT_CPU max CPU time (MIN)
|
||||||
|
* [Uu]: u = RLIMIT_NPROC max number of processes
|
||||||
|
* [Kk]: k = file creation masK (umask)
|
||||||
|
* [Ll]: l = max number of logins for this user
|
||||||
|
* [Pp]: p = process priority -20..20 (negative = high, positive = low)
|
||||||
|
*
|
||||||
|
* Return value:
|
||||||
|
* 0 = okay, of course
|
||||||
|
* LOGIN_ERROR_RLIMIT = error setting some RLIMIT
|
||||||
|
* LOGIN_ERROR_LOGIN = error - too many logins for this user
|
||||||
|
*
|
||||||
|
* buf - the limits string
|
||||||
|
* name - the username
|
||||||
|
*/
|
||||||
|
int do_user_limits(const char *buf, const char *name)
|
||||||
|
{
|
||||||
|
const char *pp;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
pp = buf;
|
||||||
|
|
||||||
|
while (*pp != '\0') switch(*pp++) {
|
||||||
|
#ifdef RLIMIT_AS
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
/* RLIMIT_AS - max address space (KB) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_AS, pp, 1024);
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_CPU
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
/* RLIMIT_CPU - max CPU time (MIN) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_CPU, pp, 60);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_DATA
|
||||||
|
case 'd':
|
||||||
|
case 'D':
|
||||||
|
/* RLIMIT_DATA - max data size (KB) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_DATA, pp, 1024);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_FSIZE
|
||||||
|
case 'f':
|
||||||
|
case 'F':
|
||||||
|
/* RLIMIT_FSIZE - Maximum filesize (KB) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_FSIZE, pp, 1024);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_NPROC
|
||||||
|
case 'u':
|
||||||
|
case 'U':
|
||||||
|
/* RLIMIT_NPROC - max number of processes */
|
||||||
|
retval |= setrlimit_value(RLIMIT_NPROC, pp, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_CORE
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
/* RLIMIT_CORE - max core file size (KB) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_CORE, pp, 1024);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_MEMLOCK
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
/* RLIMIT_MEMLOCK - max locked-in-memory address space (KB) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_MEMLOCK, pp, 1024);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_NOFILE
|
||||||
|
case 'n':
|
||||||
|
case 'N':
|
||||||
|
/* RLIMIT_NOFILE - max number of open files */
|
||||||
|
retval |= setrlimit_value(RLIMIT_NOFILE, pp, 1);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_RSS
|
||||||
|
case 'r':
|
||||||
|
case 'R':
|
||||||
|
/* RLIMIT_RSS - max resident set size (KB) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_RSS, pp, 1024);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef RLIMIT_STACK
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
/* RLIMIT_STACK - max stack size (KB) */
|
||||||
|
retval |= setrlimit_value(RLIMIT_STACK, pp, 1024);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 'k':
|
||||||
|
case 'K':
|
||||||
|
retval |= set_umask(pp);
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
/* LIMIT the number of concurent logins */
|
||||||
|
retval |= check_logins(name, pp);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
case 'P':
|
||||||
|
retval |= set_prio(pp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int setup_user_limits(const char *uname)
|
||||||
|
{
|
||||||
|
/* TODO: allow and use @group syntax --cristiang */
|
||||||
|
FILE *fil;
|
||||||
|
char buf[1024];
|
||||||
|
char name[1024];
|
||||||
|
char limits[1024];
|
||||||
|
char deflimits[1024];
|
||||||
|
char tempbuf[1024];
|
||||||
|
|
||||||
|
/* init things */
|
||||||
|
memzero(buf, sizeof(buf));
|
||||||
|
memzero(name, sizeof(name));
|
||||||
|
memzero(limits, sizeof(limits));
|
||||||
|
memzero(deflimits, sizeof(deflimits));
|
||||||
|
memzero(tempbuf, sizeof(tempbuf));
|
||||||
|
|
||||||
|
/* start the checks */
|
||||||
|
fil = fopen(LIMITS_FILE, "r");
|
||||||
|
if (fil == NULL) {
|
||||||
|
#if 0 /* no limits file is ok, not everyone is a BOFH :-). --marekm */
|
||||||
|
SYSLOG((LOG_WARN, NO_LIMITS, uname, LIMITS_FILE));
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* The limits file have the following format:
|
||||||
|
* - '#' (comment) chars only as first chars on a line;
|
||||||
|
* - username must start on first column
|
||||||
|
* A better (smarter) checking should be done --cristiang */
|
||||||
|
while (fgets(buf, 1024, fil) != NULL) {
|
||||||
|
if (buf[0]=='#' || buf[0]=='\n')
|
||||||
|
continue;
|
||||||
|
memzero(tempbuf, sizeof(tempbuf));
|
||||||
|
/* a valid line should have a username, then spaces,
|
||||||
|
* then limits
|
||||||
|
* we allow the format:
|
||||||
|
* username L2 D2048 R4096
|
||||||
|
* where spaces={' ',\t}. Also, we reject invalid limits.
|
||||||
|
* Imposing a limit should be done with care, so a wrong
|
||||||
|
* entry means no care anyway :-). A '-' as a limits
|
||||||
|
* strings means no limits --cristiang */
|
||||||
|
if (sscanf(buf, "%s%[ACDFMNRSTULPacdfmnrstulp0-9 \t-]",
|
||||||
|
name, tempbuf) == 2) {
|
||||||
|
if (strcmp(name, uname) == 0) {
|
||||||
|
strcpy(limits, tempbuf);
|
||||||
|
break;
|
||||||
|
} else if (strcmp(name, "*") == 0) {
|
||||||
|
strcpy(deflimits, tempbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fil);
|
||||||
|
if (limits[0] == '\0') {
|
||||||
|
/* no user specific limits */
|
||||||
|
if (deflimits[0] == '\0') /* no default limits */
|
||||||
|
return 0;
|
||||||
|
strcpy(limits, deflimits); /* use the default limits */
|
||||||
|
}
|
||||||
|
return do_user_limits(limits, uname);
|
||||||
|
}
|
||||||
|
#endif /* LIMITS */
|
||||||
|
|
||||||
|
|
||||||
|
void setup_usergroups(const struct passwd *info)
|
||||||
|
{
|
||||||
|
const struct group *grp;
|
||||||
|
mode_t oldmask;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if not root, and uid == gid, and username is the same as primary
|
||||||
|
* group name, set umask group bits to be the same as owner bits
|
||||||
|
* (examples: 022 -> 002, 077 -> 007).
|
||||||
|
*/
|
||||||
|
if (info->pw_uid != 0 && info->pw_uid == info->pw_gid) {
|
||||||
|
grp = getgrgid(info->pw_gid);
|
||||||
|
if (grp && (strcmp(info->pw_name, grp->gr_name) == 0)) {
|
||||||
|
oldmask = umask(0777);
|
||||||
|
umask((oldmask & ~070) | ((oldmask >> 3) & 070));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* set the process nice, ulimit, and umask from the password file entry
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setup_limits(const struct passwd *info)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
int i;
|
||||||
|
long l;
|
||||||
|
|
||||||
|
if (getdef_bool("USERGROUPS_ENAB"))
|
||||||
|
setup_usergroups(info);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if the GECOS field contains values for NICE, UMASK or ULIMIT.
|
||||||
|
* If this feature is enabled in /etc/login.defs, we make those
|
||||||
|
* values the defaults for this login session.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (getdef_bool("QUOTAS_ENAB")) {
|
||||||
|
#ifdef LIMITS
|
||||||
|
if (info->pw_uid != 0)
|
||||||
|
if (setup_user_limits(info->pw_name) & LOGIN_ERROR_LOGIN) {
|
||||||
|
fprintf(stderr, _("Too many logins.\n"));
|
||||||
|
sleep(2);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
for (cp = info->pw_gecos ; cp != NULL ; cp = strchr (cp, ',')) {
|
||||||
|
if (*cp == ',')
|
||||||
|
cp++;
|
||||||
|
|
||||||
|
if (strncmp (cp, "pri=", 4) == 0) {
|
||||||
|
i = atoi (cp + 4);
|
||||||
|
if (i >= -20 && i <= 20)
|
||||||
|
(void) nice (i);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strncmp (cp, "ulimit=", 7) == 0) {
|
||||||
|
l = strtol (cp + 7, (char **) 0, 10);
|
||||||
|
set_filesize_limit(l);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strncmp (cp, "umask=", 6) == 0) {
|
||||||
|
i = strtol (cp + 6, (char **) 0, 8) & 0777;
|
||||||
|
(void) umask (i);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
16
mbsebbs/limits.h
Normal file
16
mbsebbs/limits.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _LIMITS_H_
|
||||||
|
#define _LIMITS_H_
|
||||||
|
|
||||||
|
|
||||||
|
int setrlimit_value(unsigned int, const char *, unsigned int);
|
||||||
|
int set_prio(const char *);
|
||||||
|
int set_umask(const char *);
|
||||||
|
int check_logins(const char *, const char *);
|
||||||
|
int do_user_limits(const char *, const char *);
|
||||||
|
int setup_user_limits(const char *);
|
||||||
|
void setup_usergroups(const struct passwd *);
|
||||||
|
void setup_limits(const struct passwd *);
|
||||||
|
|
||||||
|
#endif
|
101
mbsebbs/log.c
Normal file
101
mbsebbs/log.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#if HAVE_LASTLOG_H
|
||||||
|
#include <lastlog.h>
|
||||||
|
#else
|
||||||
|
// #include "lastlog_.h"
|
||||||
|
#endif
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dolastlog - create lastlog entry
|
||||||
|
*
|
||||||
|
* A "last login" entry is created for the user being logged in. The
|
||||||
|
* UID is extracted from the global (struct passwd) entry and the
|
||||||
|
* TTY information is gotten from the (struct utmp).
|
||||||
|
*/
|
||||||
|
|
||||||
|
void dolastlog(struct lastlog *ll, const struct passwd *pw, const char *line, const char *host)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
off_t offset;
|
||||||
|
struct lastlog newlog;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the file does not exist, don't create it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((fd = open(LASTLOG_FILE, O_RDWR)) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The file is indexed by UID number. Seek to the record
|
||||||
|
* for this UID. Negative UID's will create problems, but ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
offset = (unsigned long) pw->pw_uid * sizeof newlog;
|
||||||
|
|
||||||
|
if (lseek(fd, offset, SEEK_SET) != offset) {
|
||||||
|
close(fd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the old entry so we can tell the user when they last
|
||||||
|
* logged in. Then construct the new entry and write it out
|
||||||
|
* the way we read the old one in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (read(fd, (char *) &newlog, sizeof newlog) != sizeof newlog)
|
||||||
|
memzero(&newlog, sizeof newlog);
|
||||||
|
if (ll)
|
||||||
|
*ll = newlog;
|
||||||
|
|
||||||
|
time(&newlog.ll_time);
|
||||||
|
strncpy(newlog.ll_line, line, sizeof newlog.ll_line);
|
||||||
|
#if HAVE_LL_HOST
|
||||||
|
strncpy(newlog.ll_host, host, sizeof newlog.ll_host);
|
||||||
|
#endif
|
||||||
|
if (lseek(fd, offset, SEEK_SET) == offset)
|
||||||
|
write(fd, (char *) &newlog, sizeof newlog);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
8
mbsebbs/log.h
Normal file
8
mbsebbs/log.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _LOG_LOG_H
|
||||||
|
#define _LOG_LOG_H
|
||||||
|
|
||||||
|
void dolastlog(struct lastlog *, const struct passwd *, const char *, const char *);
|
||||||
|
|
||||||
|
#endif
|
168
mbsebbs/loginprompt.c
Normal file
168
mbsebbs/loginprompt.c
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2002
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "env.h"
|
||||||
|
#include "loginprompt.h"
|
||||||
|
|
||||||
|
|
||||||
|
void login_exit(int sig)
|
||||||
|
{
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* login_prompt - prompt the user for their login name
|
||||||
|
*
|
||||||
|
* login_prompt() displays the standard login prompt. If ISSUE_FILE
|
||||||
|
* is set in login.defs, this file is displayed before the prompt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void login_prompt(const char *prompt, char *name, int namesize)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
#define MAX_ENV 32
|
||||||
|
char *envp[MAX_ENV];
|
||||||
|
int envc;
|
||||||
|
char *cp;
|
||||||
|
int i;
|
||||||
|
FILE *fp;
|
||||||
|
RETSIGTYPE (*sigquit)(int);
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
RETSIGTYPE (*sigtstp)(int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There is a small chance that a QUIT character will be part of
|
||||||
|
* some random noise during a prompt. Deal with this by exiting
|
||||||
|
* instead of core dumping. If SIGTSTP is defined, do the same
|
||||||
|
* thing for that signal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sigquit = signal(SIGQUIT, login_exit);
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
sigtstp = signal(SIGTSTP, login_exit);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* See if the user has configured the issue file to
|
||||||
|
* be displayed and display it before the prompt.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (prompt) {
|
||||||
|
cp = getdef_str("ISSUE_FILE");
|
||||||
|
if (cp && (fp = fopen(cp, "r"))) {
|
||||||
|
while ((i = getc(fp)) != EOF)
|
||||||
|
putc(i, stdout);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
gethostname(buf, sizeof buf);
|
||||||
|
printf(prompt, buf);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the user's response. The trailing newline will be
|
||||||
|
* removed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memzero(buf, sizeof buf);
|
||||||
|
if (fgets(buf, sizeof buf, stdin) != buf)
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
cp = strchr(buf, '\n');
|
||||||
|
if (!cp)
|
||||||
|
exit(1);
|
||||||
|
*cp = '\0'; /* remove \n [ must be there ] */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip leading whitespace. This makes " username" work right.
|
||||||
|
* Then copy the rest (up to the end or the first "non-graphic"
|
||||||
|
* character into the username.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
|
||||||
|
;
|
||||||
|
|
||||||
|
// for (i = 0; i < namesize - 1 && isgraph(*cp); name[i++] = *cp++);
|
||||||
|
/*
|
||||||
|
* Allow double names for Fidonet login style.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < namesize - 1 && isprint(*cp); name[i++] = *cp++);
|
||||||
|
while (isgraph(*cp))
|
||||||
|
cp++;
|
||||||
|
|
||||||
|
if (*cp)
|
||||||
|
cp++;
|
||||||
|
|
||||||
|
name[i] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a disaster, at best. The user may have entered extra
|
||||||
|
* environmental variables at the prompt. There are several ways
|
||||||
|
* to do this, and I just take the easy way out.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (*cp != '\0') { /* process new variables */
|
||||||
|
char *nvar;
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
for (envc = 0; envc < MAX_ENV; envc++) {
|
||||||
|
nvar = strtok(envc ? (char *)0 : cp, " \t,");
|
||||||
|
if (!nvar)
|
||||||
|
break;
|
||||||
|
if (strchr(nvar, '=')) {
|
||||||
|
envp[envc] = nvar;
|
||||||
|
} else {
|
||||||
|
envp[envc] = xmalloc(strlen(nvar) + 32);
|
||||||
|
sprintf(envp[envc], "L%d=%s", count++, nvar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_env(envc, envp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the SIGQUIT handler back to its original value
|
||||||
|
*/
|
||||||
|
|
||||||
|
signal(SIGQUIT, sigquit);
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
signal(SIGTSTP, sigtstp);
|
||||||
|
#endif
|
||||||
|
}
|
9
mbsebbs/loginprompt.h
Normal file
9
mbsebbs/loginprompt.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _LOGINPROMPT_H
|
||||||
|
#define _LOGINPROMPT_H
|
||||||
|
|
||||||
|
void login_exit(int);
|
||||||
|
void login_prompt(const char *, char *, int);
|
||||||
|
|
||||||
|
#endif
|
890
mbsebbs/mblogin.c
Normal file
890
mbsebbs/mblogin.c
Normal file
@ -0,0 +1,890 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: Login program for MBSE BBS.
|
||||||
|
* Shadow Suite (c) ......: Julianne Frances Haugh
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#if defined(SHADOW_PASSWORD)
|
||||||
|
#include <shadow.h>
|
||||||
|
#endif
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
#include <utmpx.h>
|
||||||
|
#else
|
||||||
|
#include <utmp.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <lastlog.h>
|
||||||
|
#include "getdef.h"
|
||||||
|
|
||||||
|
#ifdef SVR4_SI86_EUA
|
||||||
|
#include <sys/proc.h>
|
||||||
|
#include <sys/sysi86.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UT_ADDR
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "env.h"
|
||||||
|
#include "chowntty.h"
|
||||||
|
#include "ttytype.h"
|
||||||
|
#include "basename.h"
|
||||||
|
#include "shell.h"
|
||||||
|
#include "failure.h"
|
||||||
|
#include "pwdcheck.h"
|
||||||
|
#include "pwauth.h"
|
||||||
|
#include "loginprompt.h"
|
||||||
|
#include "utmp.h"
|
||||||
|
#include "limits.h"
|
||||||
|
#include "setupenv.h"
|
||||||
|
#include "sub.h"
|
||||||
|
#include "ulimit.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "tz.h"
|
||||||
|
#include "setugid.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Needed for MkLinux DR1/2/2.1 - J.
|
||||||
|
*/
|
||||||
|
#ifndef LASTLOG_FILE
|
||||||
|
#define LASTLOG_FILE "/var/log/lastlog"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *hostname = "";
|
||||||
|
|
||||||
|
struct passwd pwent, *pw;
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
struct utmpx utxent, failent;
|
||||||
|
struct utmp utent;
|
||||||
|
#else
|
||||||
|
struct utmp utent, failent;
|
||||||
|
#endif
|
||||||
|
struct lastlog lastlog;
|
||||||
|
static int preauth_flag = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int hflg = 0;
|
||||||
|
static int pflg = 0;
|
||||||
|
static char *Prog;
|
||||||
|
static int amroot;
|
||||||
|
static int timeout;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External identifiers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern char **newenvp;
|
||||||
|
extern size_t newenvc;
|
||||||
|
extern int optind;
|
||||||
|
extern char *optarg;
|
||||||
|
extern char **environ;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ALARM
|
||||||
|
#define ALARM 60
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RETRIES
|
||||||
|
#define RETRIES 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct faillog faillog;
|
||||||
|
|
||||||
|
#define NO_SHADOW "no shadow password for `%s'%s\n"
|
||||||
|
#define BAD_PASSWD "invalid password for `%s'%s\n"
|
||||||
|
#define BAD_DIALUP "invalid dialup password for `%s' on `%s'\n"
|
||||||
|
#define BAD_ROOT_LOGIN "ILLEGAL ROOT LOGIN%s\n"
|
||||||
|
#define BAD_GROUP "user `%s' not in group bbs\n"
|
||||||
|
#define ROOT_LOGIN "ROOT LOGIN%s\n"
|
||||||
|
#define FAILURE_CNT "exceeded failure limit for `%s'%s\n"
|
||||||
|
#define REG_LOGIN "`%s' logged in%s\n"
|
||||||
|
#define LOGIN_REFUSED "LOGIN `%s' REFUSED%s\n"
|
||||||
|
#define REENABLED2 \
|
||||||
|
"login `%s' re-enabled after temporary lockout (%d failures).\n"
|
||||||
|
#define MANY_FAILS "REPEATED login failures%s\n"
|
||||||
|
|
||||||
|
/* local function prototypes */
|
||||||
|
static void usage(void);
|
||||||
|
static void setup_tty(void);
|
||||||
|
static void check_flags(int, char * const *);
|
||||||
|
static void check_nologin(void);
|
||||||
|
static void init_env(void);
|
||||||
|
static RETSIGTYPE alarm_handler(int);
|
||||||
|
int main(int, char **);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* usage - print login command usage and exit
|
||||||
|
*
|
||||||
|
* login [ name ]
|
||||||
|
* login -r hostname (for rlogind)
|
||||||
|
* login -h hostname (for telnetd, etc.)
|
||||||
|
* login -f name (for pre-authenticated login: datakit, xterm, etc.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, _("usage: %s [-p] [name]\n"), Prog);
|
||||||
|
if (!amroot)
|
||||||
|
exit(1);
|
||||||
|
fprintf(stderr, _(" %s [-p] [-h host] [-f name]\n"), Prog);
|
||||||
|
#ifdef RLOGIN
|
||||||
|
fprintf(stderr, _(" %s [-p] -r host\n"), Prog);
|
||||||
|
#endif
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void setup_tty(void)
|
||||||
|
{
|
||||||
|
TERMIO termio;
|
||||||
|
|
||||||
|
GTTY(0, &termio); /* get terminal characteristics */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add your favorite terminal modes here ...
|
||||||
|
*/
|
||||||
|
termio.c_lflag |= ISIG|ICANON|ECHO|ECHOE;
|
||||||
|
termio.c_iflag |= ICRNL;
|
||||||
|
|
||||||
|
#if defined(ECHOKE) && defined(ECHOCTL)
|
||||||
|
termio.c_lflag |= ECHOKE|ECHOCTL;
|
||||||
|
#endif
|
||||||
|
#if defined(ECHOPRT) && defined(NOFLSH) && defined(TOSTOP)
|
||||||
|
termio.c_lflag &= ~(ECHOPRT|NOFLSH|TOSTOP);
|
||||||
|
#endif
|
||||||
|
#ifdef ONLCR
|
||||||
|
termio.c_oflag |= ONLCR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SUN4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Terminal setup for SunOS 4.1 courtesy of Steve Allen
|
||||||
|
* at UCO/Lick.
|
||||||
|
*/
|
||||||
|
|
||||||
|
termio.c_cc[VEOF] = '\04';
|
||||||
|
termio.c_cflag &= ~CSIZE;
|
||||||
|
termio.c_cflag |= (PARENB|CS7);
|
||||||
|
termio.c_lflag |= (ISIG|ICANON|ECHO|IEXTEN);
|
||||||
|
termio.c_iflag |= (BRKINT|IGNPAR|ISTRIP|IMAXBEL|ICRNL|IXON);
|
||||||
|
termio.c_iflag &= ~IXANY;
|
||||||
|
termio.c_oflag |= (XTABS|OPOST|ONLCR);
|
||||||
|
#endif
|
||||||
|
/* leave these values unchanged if not specified in login.defs */
|
||||||
|
termio.c_cc[VERASE] = getdef_num("ERASECHAR", termio.c_cc[VERASE]);
|
||||||
|
termio.c_cc[VKILL] = getdef_num("KILLCHAR", termio.c_cc[VKILL]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ttymon invocation prefers this, but these settings won't come into
|
||||||
|
* effect after the first username login
|
||||||
|
*/
|
||||||
|
|
||||||
|
STTY(0, &termio);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void check_flags(int argc, char * const *argv)
|
||||||
|
{
|
||||||
|
int arg;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the flags for proper form. Every argument starting with
|
||||||
|
* "-" must be exactly two characters long. This closes all the
|
||||||
|
* clever rlogin, telnet, and getty holes.
|
||||||
|
*/
|
||||||
|
for (arg = 1; arg < argc; arg++) {
|
||||||
|
// printf("%d <%s>\n", arg, argv[arg]);
|
||||||
|
if (argv[arg][0] == '-' && strlen(argv[arg]) > 2)
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void check_nologin(void)
|
||||||
|
{
|
||||||
|
char *fname;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to see if system is turned off for non-root users.
|
||||||
|
* This would be useful to prevent users from logging in
|
||||||
|
* during system maintenance. We make sure the message comes
|
||||||
|
* out for root so she knows to remove the file if she's
|
||||||
|
* forgotten about it ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
fname = getdef_str("NOLOGINS_FILE");
|
||||||
|
if (fname != NULL && access(fname, F_OK) == 0) {
|
||||||
|
FILE *nlfp;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cat the file if it can be opened, otherwise just
|
||||||
|
* print a default message
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((nlfp = fopen (fname, "r"))) {
|
||||||
|
while ((c = getc (nlfp)) != EOF) {
|
||||||
|
if (c == '\n')
|
||||||
|
putchar ('\r');
|
||||||
|
|
||||||
|
putchar (c);
|
||||||
|
}
|
||||||
|
fflush (stdout);
|
||||||
|
fclose (nlfp);
|
||||||
|
} else
|
||||||
|
printf("\nSystem closed for routine maintenance\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Non-root users must exit. Root gets the message, but
|
||||||
|
* gets to login.
|
||||||
|
*/
|
||||||
|
if (pwent.pw_uid != 0) {
|
||||||
|
closelog();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
printf("\n[Disconnect bypassed -- root login allowed.]\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void init_env(void)
|
||||||
|
{
|
||||||
|
char *cp, *tmp;
|
||||||
|
|
||||||
|
if ((tmp = getenv("LANG"))) {
|
||||||
|
addenv("LANG", tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the timezone environmental variable so that time functions
|
||||||
|
* work correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((tmp = getenv("TZ"))) {
|
||||||
|
addenv("TZ", tmp);
|
||||||
|
} else if ((cp = getdef_str("ENV_TZ")))
|
||||||
|
addenv(*cp == '/' ? tz(cp) : cp, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the clock frequency so that profiling commands work
|
||||||
|
* correctly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((tmp = getenv("HZ"))) {
|
||||||
|
addenv("HZ", tmp);
|
||||||
|
} else if ((cp = getdef_str("ENV_HZ")))
|
||||||
|
addenv(cp, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static RETSIGTYPE alarm_handler(int sig)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "\nLogin timed out after %d seconds.\n", timeout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* login - create a new login session for a user
|
||||||
|
*
|
||||||
|
* login is typically called by getty as the second step of a
|
||||||
|
* new user session. getty is responsible for setting the line
|
||||||
|
* characteristics to a reasonable set of values and getting
|
||||||
|
* the name of the user to be logged in. login may also be
|
||||||
|
* called to create a new user session on a pty for a variety
|
||||||
|
* of reasons, such as X servers or network logins.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char username[37];
|
||||||
|
char tty[BUFSIZ];
|
||||||
|
char userfile[PATH_MAX];
|
||||||
|
FILE *ufp;
|
||||||
|
struct userhdr usrconfighdr;
|
||||||
|
struct userrec usrconfig;
|
||||||
|
int reason = PW_LOGIN;
|
||||||
|
int delay;
|
||||||
|
int retries;
|
||||||
|
int failed;
|
||||||
|
int flag;
|
||||||
|
int subroot = 0;
|
||||||
|
int is_console = 0;
|
||||||
|
int FoundName;
|
||||||
|
const char *cp;
|
||||||
|
char *tmp;
|
||||||
|
char fromhost[512];
|
||||||
|
struct passwd *pwd;
|
||||||
|
char **envp = environ;
|
||||||
|
static char temp_pw[2];
|
||||||
|
static char temp_shell[] = "/bin/sh";
|
||||||
|
#ifdef SHADOW_PASSWORD
|
||||||
|
struct spwd *spwd=NULL;
|
||||||
|
#endif
|
||||||
|
#if defined(DES_RPC) || defined(KERBEROS)
|
||||||
|
/* from pwauth.c */
|
||||||
|
extern char *clear_pass;
|
||||||
|
extern int wipe_clear_pass;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We may need the password later, don't want pw_auth() to wipe it
|
||||||
|
* (we do it ourselves when it is no longer needed). --marekm
|
||||||
|
*/
|
||||||
|
wipe_clear_pass = 0;
|
||||||
|
#endif
|
||||||
|
printf("\nMBSE BBS v%s\n", VERSION);
|
||||||
|
printf("%s\n\n", COPYRIGHT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some quick initialization.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sanitize_env();
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
|
textdomain(PACKAGE);
|
||||||
|
|
||||||
|
initenv();
|
||||||
|
|
||||||
|
username[0] = '\0';
|
||||||
|
amroot = (getuid() == 0);
|
||||||
|
Prog = Basename(argv[0]);
|
||||||
|
|
||||||
|
check_flags(argc, argv);
|
||||||
|
|
||||||
|
while ((flag = getopt(argc, argv, "d:h:p")) != EOF) {
|
||||||
|
switch (flag) {
|
||||||
|
case 'p':
|
||||||
|
pflg++;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
hflg++;
|
||||||
|
hostname = optarg;
|
||||||
|
reason = PW_TELNET;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
/* "-d device" ignored for compatibility */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow authentication bypass only if real UID is zero.
|
||||||
|
*/
|
||||||
|
if (hflg && !amroot) {
|
||||||
|
fprintf(stderr, _("%s: permission denied\n"), Prog);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isatty(0) || !isatty(1) || !isatty(2))
|
||||||
|
exit(1); /* must be a terminal */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Be picky if run by normal users (possible if installed setuid
|
||||||
|
* root), but not if run by root. This way it still allows logins
|
||||||
|
* even if your getty is broken, or if something corrupts utmp,
|
||||||
|
* but users must "exec login" which will use the existing utmp
|
||||||
|
* entry (will not overwrite remote hostname). --marekm
|
||||||
|
*/
|
||||||
|
checkutmp(!amroot);
|
||||||
|
STRFCPY(tty, utent.ut_line);
|
||||||
|
|
||||||
|
if (hflg) {
|
||||||
|
#ifdef UT_ADDR
|
||||||
|
struct hostent *he;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in the ut_addr field (remote login IP address).
|
||||||
|
* XXX - login from util-linux does it, but this is not
|
||||||
|
* the right place to do it. The program that starts
|
||||||
|
* login (telnetd, rlogind) knows the IP address, so it
|
||||||
|
* should create the utmp entry and fill in ut_addr.
|
||||||
|
* gethostbyname() is not 100% reliable (the remote host
|
||||||
|
* may be unknown, etc.). --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((he = gethostbyname(hostname))) {
|
||||||
|
utent.ut_addr = *((int32_t *)(he->h_addr_list[0]));
|
||||||
|
#endif
|
||||||
|
#ifdef UT_HOST
|
||||||
|
strncpy(utent.ut_host, hostname, sizeof(utent.ut_host));
|
||||||
|
#endif
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
strncpy(utxent.ut_host, hostname, sizeof(utxent.ut_host));
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Add remote hostname to the environment. I think
|
||||||
|
* (not sure) I saw it once on Irix. --marekm
|
||||||
|
*/
|
||||||
|
addenv("REMOTEHOST", hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
/* workaround for init/getty leaving junk in ut_host at least in some
|
||||||
|
version of RedHat. --marekm */
|
||||||
|
else if (amroot)
|
||||||
|
memzero(utent.ut_host, sizeof utent.ut_host);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
openlog("mblogin", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
|
||||||
|
|
||||||
|
setup_tty();
|
||||||
|
|
||||||
|
umask(getdef_num("UMASK", 077));
|
||||||
|
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Use the ULIMIT in the login.defs file, and if
|
||||||
|
* there isn't one, use the default value. The
|
||||||
|
* user may have one for themselves, but otherwise,
|
||||||
|
* just take what you get.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long limit = getdef_long("ULIMIT", -1L);
|
||||||
|
|
||||||
|
if (limit != -1)
|
||||||
|
set_filesize_limit(limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pflg)
|
||||||
|
while (*envp) /* add inherited environment, */
|
||||||
|
addenv(*envp++, NULL); /* some variables change later */
|
||||||
|
|
||||||
|
/* preserve TERM from getty */
|
||||||
|
if (!pflg && (tmp = getenv("TERM")))
|
||||||
|
addenv("TERM", tmp);
|
||||||
|
|
||||||
|
/* preserver CONNECT messages from mgetty */
|
||||||
|
if ((tmp = getenv("CONNECT")))
|
||||||
|
addenv("CONNECT", tmp);
|
||||||
|
if ((tmp = getenv("CALLER_ID")))
|
||||||
|
addenv("CALLER_ID", tmp);
|
||||||
|
|
||||||
|
/* get the mbse environment */
|
||||||
|
pw = getpwnam("mbse");
|
||||||
|
addenv("MBSE_ROOT", pw->pw_dir);
|
||||||
|
sprintf(userfile, "%s/etc/users.data", pw->pw_dir);
|
||||||
|
|
||||||
|
init_env();
|
||||||
|
|
||||||
|
if (optind < argc) { /* get the user name */
|
||||||
|
// if (rflg || fflg)
|
||||||
|
// usage();
|
||||||
|
|
||||||
|
#ifdef SVR4
|
||||||
|
/*
|
||||||
|
* The "-h" option can't be used with a command-line username,
|
||||||
|
* because telnetd invokes us as: login -h host TERM=...
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (! hflg)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
STRFCPY(username, argv[optind]);
|
||||||
|
strzero(argv[optind]);
|
||||||
|
++optind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[%s]\n", username);
|
||||||
|
|
||||||
|
#ifdef SVR4
|
||||||
|
/*
|
||||||
|
* check whether ttymon has done the prompt for us already
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
char *ttymon_prompt;
|
||||||
|
|
||||||
|
if ((ttymon_prompt = getenv("TTYPROMPT")) != NULL && (*ttymon_prompt != 0)) {
|
||||||
|
/* read name, without prompt */
|
||||||
|
login_prompt((char *)0, username, sizeof username);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* SVR4 */
|
||||||
|
if (optind < argc) /* now set command line variables */
|
||||||
|
set_env(argc - optind, &argv[optind]);
|
||||||
|
|
||||||
|
if (hflg)
|
||||||
|
cp = hostname;
|
||||||
|
else
|
||||||
|
#ifdef UT_HOST
|
||||||
|
if (utent.ut_host[0])
|
||||||
|
cp = utent.ut_host;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
if (utxent.ut_host[0])
|
||||||
|
cp = utxent.ut_host;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
cp = "";
|
||||||
|
|
||||||
|
if (*cp)
|
||||||
|
snprintf(fromhost, sizeof fromhost, _(" on `%s' from `%s'"), tty, cp);
|
||||||
|
else
|
||||||
|
snprintf(fromhost, sizeof fromhost, _(" on `%s'"), tty);
|
||||||
|
|
||||||
|
top:
|
||||||
|
/* only allow ALARM sec. for login */
|
||||||
|
signal(SIGALRM, alarm_handler);
|
||||||
|
timeout = getdef_num("LOGIN_TIMEOUT", ALARM);
|
||||||
|
if (timeout > 0)
|
||||||
|
alarm(timeout);
|
||||||
|
|
||||||
|
environ = newenvp; /* make new environment active */
|
||||||
|
delay = getdef_num("FAIL_DELAY", 1);
|
||||||
|
retries = getdef_num("LOGIN_RETRIES", RETRIES);
|
||||||
|
|
||||||
|
while (1) { /* repeatedly get login/password pairs */
|
||||||
|
failed = 0; /* haven't failed authentication yet */
|
||||||
|
if (! username[0]) { /* need to get a login id */
|
||||||
|
if (subroot) {
|
||||||
|
closelog ();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
preauth_flag = 0;
|
||||||
|
#ifndef LOGIN_PROMPT
|
||||||
|
#ifdef __linux__ /* hostname login: - like in util-linux login */
|
||||||
|
login_prompt(_("\n%s login: "), username, sizeof username);
|
||||||
|
#else
|
||||||
|
login_prompt(_("login: "), username, sizeof username);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
login_prompt(LOGIN_PROMPT, username, sizeof username);
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we try usernames on unix names and Fidonet style
|
||||||
|
* names that are stored in the bbs userdatabase.
|
||||||
|
*/
|
||||||
|
FoundName = 0;
|
||||||
|
if ((ufp = fopen(userfile, "r"))) {
|
||||||
|
fread(&usrconfighdr, sizeof(usrconfighdr), 1, ufp);
|
||||||
|
while (fread(&usrconfig, usrconfighdr.recsize, 1, ufp) == 1) {
|
||||||
|
if ((strcasecmp(usrconfig.sUserName, username) == 0) ||
|
||||||
|
(strcasecmp(usrconfig.sHandle, username) == 0) ||
|
||||||
|
(strcmp(usrconfig.Name, username) == 0)) {
|
||||||
|
FoundName = 1;
|
||||||
|
STRFCPY(username, usrconfig.Name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(ufp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! (pwd = getpwnam(username))) {
|
||||||
|
pwent.pw_name = username;
|
||||||
|
strcpy(temp_pw, "!");
|
||||||
|
pwent.pw_passwd = temp_pw;
|
||||||
|
pwent.pw_shell = temp_shell;
|
||||||
|
|
||||||
|
preauth_flag = 0;
|
||||||
|
failed = 1;
|
||||||
|
} else {
|
||||||
|
pwent = *pwd;
|
||||||
|
}
|
||||||
|
#ifdef SHADOW_PASSWORD
|
||||||
|
spwd = NULL;
|
||||||
|
if (pwd && strcmp(pwd->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
|
||||||
|
spwd = getspnam(username);
|
||||||
|
if (spwd)
|
||||||
|
pwent.pw_passwd = spwd->sp_pwdp;
|
||||||
|
else
|
||||||
|
syslog(LOG_WARNING, NO_SHADOW, username, fromhost);
|
||||||
|
}
|
||||||
|
#endif /* SHADOWPWD */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the encrypted password begins with a "!", the account
|
||||||
|
* is locked and the user cannot login, even if they have
|
||||||
|
* been "pre-authenticated."
|
||||||
|
*/
|
||||||
|
if (pwent.pw_passwd[0] == '!' || pwent.pw_passwd[0] == '*')
|
||||||
|
failed = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The -r and -f flags provide a name which has already
|
||||||
|
* been authenticated by some server.
|
||||||
|
*/
|
||||||
|
if (preauth_flag)
|
||||||
|
goto auth_ok;
|
||||||
|
|
||||||
|
if (pw_auth(pwent.pw_passwd, username, reason, (char *) 0) == 0)
|
||||||
|
goto auth_ok;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't log unknown usernames - I mistyped the password for
|
||||||
|
* username at least once... Should probably use LOG_AUTHPRIV
|
||||||
|
* for those who really want to log them. --marekm
|
||||||
|
*/
|
||||||
|
syslog(LOG_WARNING, BAD_PASSWD, (pwd || getdef_bool("LOG_UNKFAIL_ENAB")) ? username : "UNKNOWN", fromhost);
|
||||||
|
failed = 1;
|
||||||
|
|
||||||
|
auth_ok:
|
||||||
|
/*
|
||||||
|
* This is the point where all authenticated users
|
||||||
|
* wind up. If you reach this far, your password has
|
||||||
|
* been authenticated and so on.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(RADIUS) && !(defined(DES_RPC) || defined(KERBEROS))
|
||||||
|
if (clear_pass) {
|
||||||
|
strzero(clear_pass);
|
||||||
|
clear_pass = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (! failed && pwent.pw_name && pwent.pw_uid == 0 && ! is_console) {
|
||||||
|
syslog(LOG_CRIT, BAD_ROOT_LOGIN, fromhost);
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
#ifdef LOGIN_ACCESS
|
||||||
|
if (!failed && !login_access(username, *hostname ? hostname : tty)) {
|
||||||
|
syslog(LOG_WARNING, LOGIN_REFUSED, username, fromhost);
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (pwd && getdef_bool("FAILLOG_ENAB") && ! failcheck (pwent.pw_uid, &faillog, failed)) {
|
||||||
|
syslog(LOG_CRIT, FAILURE_CNT, username, fromhost);
|
||||||
|
failed = 1;
|
||||||
|
}
|
||||||
|
if (! failed)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* don't log non-existent users */
|
||||||
|
if (pwd && getdef_bool("FAILLOG_ENAB"))
|
||||||
|
failure (pwent.pw_uid, tty, &faillog);
|
||||||
|
if (getdef_str("FTMP_FILE") != NULL) {
|
||||||
|
const char *failent_user;
|
||||||
|
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
failent = utxent;
|
||||||
|
gettimeofday(&(failent.ut_tv), NULL);
|
||||||
|
#else
|
||||||
|
failent = utent;
|
||||||
|
time(&failent.ut_time);
|
||||||
|
#endif
|
||||||
|
if (pwd) {
|
||||||
|
failent_user = pwent.pw_name;
|
||||||
|
} else {
|
||||||
|
if (getdef_bool("LOG_UNKFAIL_ENAB"))
|
||||||
|
failent_user = username;
|
||||||
|
else
|
||||||
|
failent_user = "UNKNOWN";
|
||||||
|
}
|
||||||
|
strncpy(failent.ut_user, failent_user, sizeof(failent.ut_user));
|
||||||
|
#ifdef USER_PROCESS
|
||||||
|
failent.ut_type = USER_PROCESS;
|
||||||
|
#endif
|
||||||
|
failtmp(&failent);
|
||||||
|
}
|
||||||
|
memzero(username, sizeof username);
|
||||||
|
|
||||||
|
if (--retries <= 0)
|
||||||
|
syslog(LOG_CRIT, MANY_FAILS, fromhost);
|
||||||
|
#if 1
|
||||||
|
/*
|
||||||
|
* If this was a passwordless account and we get here,
|
||||||
|
* login was denied (securetty, faillog, etc.). There
|
||||||
|
* was no password prompt, so do it now (will always
|
||||||
|
* fail - the bad guys won't see that the passwordless
|
||||||
|
* account exists at all). --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pwent.pw_passwd[0] == '\0')
|
||||||
|
pw_auth("!", username, reason, (char *) 0);
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* Wait a while (a la SVR4 /usr/bin/login) before attempting
|
||||||
|
* to login the user again. If the earlier alarm occurs
|
||||||
|
* before the sleep() below completes, login will exit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (delay > 0)
|
||||||
|
sleep(delay);
|
||||||
|
|
||||||
|
puts(_("Login incorrect"));
|
||||||
|
|
||||||
|
} /* while (1) */
|
||||||
|
(void) alarm (0); /* turn off alarm clock */
|
||||||
|
#if 1
|
||||||
|
/*
|
||||||
|
* porttime checks moved here, after the user has been
|
||||||
|
* authenticated. now prints a message, as suggested
|
||||||
|
* by Ivan Nejgebauer <ian@unsux.ns.ac.yu>. --marekm
|
||||||
|
*/
|
||||||
|
// if (getdef_bool("PORTTIME_CHECKS_ENAB") &&
|
||||||
|
// !isttytime(pwent.pw_name, tty, time ((time_t *) 0))) {
|
||||||
|
// SYSLOG((LOG_WARN, BAD_TIME, username, fromhost));
|
||||||
|
// closelog();
|
||||||
|
// bad_time_notify();
|
||||||
|
// exit(1);
|
||||||
|
// }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
check_nologin();
|
||||||
|
|
||||||
|
if (getenv("IFS")) /* don't export user IFS ... */
|
||||||
|
addenv("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
|
||||||
|
|
||||||
|
setutmp(username, tty, hostname); /* make entry in utmp & wtmp files */
|
||||||
|
if (pwent.pw_shell[0] == '*') { /* subsystem root */
|
||||||
|
subsystem (&pwent); /* figure out what to execute */
|
||||||
|
subroot++; /* say i was here again */
|
||||||
|
endpwent (); /* close all of the file which were */
|
||||||
|
endgrent (); /* open in the original rooted file */
|
||||||
|
#ifdef SHADOW_PASSWORD
|
||||||
|
endspent (); /* system. they will be re-opened */
|
||||||
|
#endif
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
endsgent (); /* in the new rooted file system */
|
||||||
|
#endif
|
||||||
|
goto top; /* go do all this all over again */
|
||||||
|
}
|
||||||
|
if (getdef_bool("LASTLOG_ENAB")) /* give last login and log this one */
|
||||||
|
dolastlog(&lastlog, &pwent, utent.ut_line, hostname);
|
||||||
|
|
||||||
|
#ifdef SVR4_SI86_EUA
|
||||||
|
sysi86(SI86LIMUSER, EUA_ADD_USER); /* how do we test for fail? */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef AGING
|
||||||
|
/*
|
||||||
|
* Have to do this while we still have root privileges, otherwise
|
||||||
|
* we don't have access to /etc/shadow. expire() closes password
|
||||||
|
* files, and changes to the user in the child before executing
|
||||||
|
* the passwd program. --marekm
|
||||||
|
*/
|
||||||
|
#ifdef SHADOW_PASSWORD
|
||||||
|
if (spwd) { /* check for age of password */
|
||||||
|
if (expire (&pwent, spwd)) {
|
||||||
|
pwd = getpwnam(username);
|
||||||
|
spwd = getspnam(username);
|
||||||
|
if (pwd)
|
||||||
|
pwent = *pwd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#ifdef ATT_AGE
|
||||||
|
if (pwent.pw_age && pwent.pw_age[0]) {
|
||||||
|
if (expire (&pwent)) {
|
||||||
|
pwd = getpwnam(username);
|
||||||
|
if (pwd)
|
||||||
|
pwent = *pwd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ATT_AGE */
|
||||||
|
#endif /* SHADOWPWD */
|
||||||
|
#endif /* AGING */
|
||||||
|
|
||||||
|
setup_limits(&pwent); /* nice, ulimit etc. */
|
||||||
|
chown_tty(tty, &pwent);
|
||||||
|
|
||||||
|
if (setup_uid_gid(&pwent, is_console))
|
||||||
|
exit(1);
|
||||||
|
|
||||||
|
#ifdef KERBEROS
|
||||||
|
if (clear_pass)
|
||||||
|
login_kerberos(username, clear_pass);
|
||||||
|
#endif
|
||||||
|
#ifdef DES_RPC
|
||||||
|
if (clear_pass)
|
||||||
|
login_desrpc(clear_pass);
|
||||||
|
#endif
|
||||||
|
#if defined(DES_RPC) || defined(KERBEROS)
|
||||||
|
if (clear_pass)
|
||||||
|
strzero(clear_pass);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
setup_env(&pwent); /* set env vars, cd to the home dir */
|
||||||
|
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
|
textdomain(PACKAGE);
|
||||||
|
|
||||||
|
addenv("HUSHLOGIN=TRUE", NULL);
|
||||||
|
|
||||||
|
if (getdef_str("TTYTYPE_FILE") != NULL && getenv("TERM") == NULL)
|
||||||
|
ttytype (tty);
|
||||||
|
|
||||||
|
signal(SIGQUIT, SIG_DFL); /* default quit signal */
|
||||||
|
signal(SIGTERM, SIG_DFL); /* default terminate signal */
|
||||||
|
signal(SIGALRM, SIG_DFL); /* default alarm signal */
|
||||||
|
signal(SIGHUP, SIG_DFL); /* added this. --marekm */
|
||||||
|
signal(SIGINT, SIG_DFL); /* default interrupt signal */
|
||||||
|
|
||||||
|
endpwent(); /* stop access to password file */
|
||||||
|
endgrent(); /* stop access to group file */
|
||||||
|
#ifdef SHADOW_PASSWORD
|
||||||
|
endspent(); /* stop access to shadow passwd file */
|
||||||
|
#endif
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
endsgent(); /* stop access to shadow group file */
|
||||||
|
#endif
|
||||||
|
if (pwent.pw_uid == 0)
|
||||||
|
syslog(LOG_NOTICE, ROOT_LOGIN, fromhost);
|
||||||
|
else
|
||||||
|
syslog(LOG_INFO, REG_LOGIN, username, fromhost);
|
||||||
|
closelog();
|
||||||
|
if ((tmp = getdef_str("FAKE_SHELL")) != NULL) {
|
||||||
|
shell(tmp, pwent.pw_shell); /* fake shell */
|
||||||
|
}
|
||||||
|
shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
|
||||||
|
/*NOTREACHED*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
365
mbsebbs/mblogin.h
Normal file
365
mbsebbs/mblogin.h
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _MBLOGIN_H
|
||||||
|
#define _MBLOGIN_H
|
||||||
|
|
||||||
|
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
|
||||||
|
|
||||||
|
/* Take care of NLS matters. */
|
||||||
|
|
||||||
|
#if HAVE_LOCALE_H
|
||||||
|
# include <locale.h>
|
||||||
|
#endif
|
||||||
|
#if !HAVE_SETLOCALE
|
||||||
|
# define setlocale(Category, Locale) /* empty */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define gettext_noop(String) (String)
|
||||||
|
/* #define gettext_def(String) "#define String" */
|
||||||
|
|
||||||
|
#if ENABLE_NLS
|
||||||
|
# include <libintl.h>
|
||||||
|
# define _(Text) gettext (Text)
|
||||||
|
#else
|
||||||
|
# undef bindtextdomain
|
||||||
|
# define bindtextdomain(Domain, Directory) /* empty */
|
||||||
|
# undef textdomain
|
||||||
|
# define textdomain(Domain) /* empty */
|
||||||
|
# define _(Text) Text
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef P_
|
||||||
|
# ifdef PROTOTYPES
|
||||||
|
# define P_(x) x
|
||||||
|
# else
|
||||||
|
# define P_(x) ()
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if STDC_HEADERS
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <string.h>
|
||||||
|
#else /* not STDC_HEADERS */
|
||||||
|
# ifndef HAVE_STRCHR
|
||||||
|
# define strchr index
|
||||||
|
# define strrchr rindex
|
||||||
|
# endif
|
||||||
|
char *strchr(), *strrchr(), *strtok();
|
||||||
|
# ifndef HAVE_MEMCPY
|
||||||
|
# define memcpy(d, s, n) bcopy((s), (d), (n))
|
||||||
|
# endif
|
||||||
|
#endif /* not STDC_HEADERS */
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#if HAVE_SYS_WAIT_H
|
||||||
|
# include <sys/wait.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TIME_WITH_SYS_TIME
|
||||||
|
# include <sys/time.h>
|
||||||
|
# include <time.h>
|
||||||
|
#else /* not TIME_WITH_SYS_TIME */
|
||||||
|
# if HAVE_SYS_TIME_H
|
||||||
|
# include <sys/time.h>
|
||||||
|
# else
|
||||||
|
# include <time.h>
|
||||||
|
# endif
|
||||||
|
#endif /* not TIME_WITH_SYS_TIME */
|
||||||
|
|
||||||
|
#ifdef HAVE_MEMSET
|
||||||
|
# define memzero(ptr, size) memset((void *)(ptr), 0, (size))
|
||||||
|
#else
|
||||||
|
# define memzero(ptr, size) bzero((char *)(ptr), (size))
|
||||||
|
#endif
|
||||||
|
#define strzero(s) memzero(s, strlen(s)) /* warning: evaluates twice */
|
||||||
|
|
||||||
|
#ifdef HAVE_DIRENT_H /* DIR_SYSV */
|
||||||
|
# include <dirent.h>
|
||||||
|
# define DIRECT dirent
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_SYS_NDIR_H /* DIR_XENIX */
|
||||||
|
# include <sys/ndir.h>
|
||||||
|
# endif
|
||||||
|
# ifdef HAVE_SYS_DIR_H /* DIR_??? */
|
||||||
|
# include <sys/dir.h>
|
||||||
|
# endif
|
||||||
|
# ifdef HAVE_NDIR_H /* DIR_BSD */
|
||||||
|
# include <ndir.h>
|
||||||
|
# endif
|
||||||
|
# define DIRECT direct
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHADOWPWD
|
||||||
|
/*
|
||||||
|
* Possible cases:
|
||||||
|
* - /usr/include/shadow.h exists and includes the shadow group stuff.
|
||||||
|
* - /usr/include/shadow.h exists, but we use our own gshadow.h.
|
||||||
|
* - /usr/include/shadow.h doesn't exist, use our own shadow.h and gshadow.h.
|
||||||
|
*/
|
||||||
|
#if HAVE_SHADOW_H
|
||||||
|
#include <shadow.h>
|
||||||
|
#if defined(SHADOWGRP) && !defined(GSHADOW)
|
||||||
|
#include "gshadow_.h"
|
||||||
|
#endif
|
||||||
|
#else /* not HAVE_SHADOW_H */
|
||||||
|
#include "shadow_.h"
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
#include "gshadow_.h"
|
||||||
|
#endif
|
||||||
|
#endif /* not HAVE_SHADOW_H */
|
||||||
|
#endif /* SHADOWPWD */
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifndef NGROUPS_MAX
|
||||||
|
#ifdef NGROUPS
|
||||||
|
#define NGROUPS_MAX NGROUPS
|
||||||
|
#else
|
||||||
|
#define NGROUPS_MAX 64
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef F_OK
|
||||||
|
# define F_OK 0
|
||||||
|
# define X_OK 1
|
||||||
|
# define W_OK 2
|
||||||
|
# define R_OK 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_TERMIOS_H
|
||||||
|
# include <termios.h>
|
||||||
|
# define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
|
||||||
|
# define GTTY(fd, termio) tcgetattr(fd, termio)
|
||||||
|
# define TERMIO struct termios
|
||||||
|
# define USE_TERMIOS
|
||||||
|
#else /* assumed HAVE_TERMIO_H */
|
||||||
|
# include <sys/ioctl.h>
|
||||||
|
# include <termio.h>
|
||||||
|
# define STTY(fd, termio) ioctl(fd, TCSETA, termio)
|
||||||
|
# define GTTY(fd, termio) ioctl(fd, TCGETA, termio)
|
||||||
|
# define TEMRIO struct termio
|
||||||
|
# define USE_TERMIO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Password aging constants
|
||||||
|
*
|
||||||
|
* DAY - seconds / day
|
||||||
|
* WEEK - seconds / week
|
||||||
|
* SCALE - seconds / aging unit
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Solaris defines this in shadow.h */
|
||||||
|
#ifndef DAY
|
||||||
|
#define DAY (24L*3600L)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WEEK (7*DAY)
|
||||||
|
|
||||||
|
#ifdef ITI_AGING
|
||||||
|
#define SCALE 1
|
||||||
|
#else
|
||||||
|
#define SCALE DAY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Copy string pointed by B to array A with size checking. It was originally
|
||||||
|
* in lmain.c but is _very_ useful elsewhere. Some setuid root programs with
|
||||||
|
* very sloppy coding used to assume that BUFSIZ will always be enough... */
|
||||||
|
|
||||||
|
/* danger - side effects */
|
||||||
|
#define STRFCPY(A,B) \
|
||||||
|
(strncpy((A), (B), sizeof(A) - 1), (A)[sizeof(A) - 1] = '\0')
|
||||||
|
|
||||||
|
/* get rid of a few ugly repeated #ifdefs in pwent.c and grent.c */
|
||||||
|
/* XXX - this is ugly too, configure should test it and not check for
|
||||||
|
any hardcoded system names, if possible. --marekm */
|
||||||
|
#if defined(SVR4) || defined(AIX) || defined(__linux__)
|
||||||
|
#define SETXXENT_TYPE void
|
||||||
|
#define SETXXENT_RET(x) return
|
||||||
|
#define SETXXENT_TEST(x) x; if (0) /* compiler should optimize this away */
|
||||||
|
#else
|
||||||
|
#define SETXXENT_TYPE int
|
||||||
|
#define SETXXENT_RET(x) return(x)
|
||||||
|
#define SETXXENT_TEST(x) if (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PASSWD_FILE
|
||||||
|
#define PASSWD_FILE "/etc/passwd"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GROUP_FILE
|
||||||
|
#define GROUP_FILE "/etc/group"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHADOWPWD
|
||||||
|
#ifndef SHADOW_FILE
|
||||||
|
#define SHADOW_FILE "/etc/shadow"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
#ifndef SGROUP_FILE
|
||||||
|
#define SGROUP_FILE "/etc/gshadow"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PASSWD_PAG_FILE PASSWD_FILE ".pag"
|
||||||
|
#define GROUP_PAG_FILE GROUP_FILE ".pag"
|
||||||
|
#define SHADOW_PAG_FILE SHADOW_FILE ".pag"
|
||||||
|
#define SGROUP_PAG_FILE SGROUP_FILE ".pag"
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL ((void *) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef sun /* hacks for compiling on SunOS */
|
||||||
|
# ifndef SOLARIS
|
||||||
|
extern int fputs();
|
||||||
|
extern char *strdup();
|
||||||
|
extern char *strerror();
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_SNPRINTF
|
||||||
|
#include "snprintf.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* string to use for the pw_passwd field in /etc/passwd when using
|
||||||
|
* shadow passwords - most systems use "x" but there are a few
|
||||||
|
* exceptions, so it can be changed here if necessary. --marekm
|
||||||
|
*/
|
||||||
|
#ifndef SHADOW_PASSWD_STRING
|
||||||
|
#define SHADOW_PASSWD_STRING "x"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PAM_STRERROR_NEEDS_TWO_ARGS /* Linux-PAM 0.59+ */
|
||||||
|
#define PAM_STRERROR(pamh, err) pam_strerror(pamh, err)
|
||||||
|
#else
|
||||||
|
#define PAM_STRERROR(pamh, err) pam_strerror(err)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* login failure logging file format
|
||||||
|
*
|
||||||
|
* The login failure file is maintained by login(1) and faillog(8)
|
||||||
|
* Each record in the file represents a separate UID and the file
|
||||||
|
* is indexed in that fashion.
|
||||||
|
*/
|
||||||
|
struct faillog {
|
||||||
|
short fail_cnt; /* failures since last success */
|
||||||
|
short fail_max; /* failures before turning account off */
|
||||||
|
char fail_line[12]; /* last failure occured here */
|
||||||
|
time_t fail_time; /* last failure occured then */
|
||||||
|
/*
|
||||||
|
* If nonzero, the account will be re-enabled if there are no
|
||||||
|
* failures for fail_locktime seconds since last failure.
|
||||||
|
*/
|
||||||
|
long fail_locktime;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define Max_passlen 14 /* Define maximum passwd length */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Security structure
|
||||||
|
*/
|
||||||
|
typedef struct _security {
|
||||||
|
unsigned int level; /* Security level */
|
||||||
|
unsigned long flags; /* Access flags */
|
||||||
|
unsigned long notflags; /* No Access flags */
|
||||||
|
} securityrec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Users Control Structures (users.data)
|
||||||
|
*/
|
||||||
|
struct userhdr {
|
||||||
|
long hdrsize; /* Size of header */
|
||||||
|
long recsize; /* Size of records */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct userrec {
|
||||||
|
char sUserName[36]; /* User First and Last Name */
|
||||||
|
char Name[9]; /* Unix name */
|
||||||
|
unsigned long xPassword; /* Users Password (CRC) */
|
||||||
|
char sVoicePhone[20]; /* Voice Number */
|
||||||
|
char sDataPhone[20]; /* Data/Business Number */
|
||||||
|
char sLocation[28]; /* Users Location */
|
||||||
|
char address[3][41]; /* Users address */
|
||||||
|
char sDateOfBirth[12]; /* Date of Birth */
|
||||||
|
time_t tFirstLoginDate; /* Date of First Login */
|
||||||
|
time_t tLastLoginDate; /* Date of Last Login */
|
||||||
|
securityrec Security; /* User Security Level */
|
||||||
|
char sComment[81]; /* User Comment */
|
||||||
|
char sExpiryDate[12]; /* User Expiry Date */
|
||||||
|
securityrec ExpirySec; /* Expiry Security Level */
|
||||||
|
char sSex[8]; /* Users Sex */
|
||||||
|
|
||||||
|
unsigned Hidden : 1; /* Hide User from Lists */
|
||||||
|
unsigned HotKeys : 1; /* Hot-Keys ON/OFF */
|
||||||
|
unsigned GraphMode : 1; /* ANSI Mode ON/OFF */
|
||||||
|
unsigned Deleted : 1; /* Deleted Status */
|
||||||
|
unsigned NeverDelete : 1; /* Never Delete User */
|
||||||
|
unsigned Chat : 1; /* Has IEMSI Chatmode */
|
||||||
|
unsigned LockedOut : 1; /* User is locked out */
|
||||||
|
unsigned DoNotDisturb : 1; /* DoNot disturb */
|
||||||
|
unsigned Cls : 1; /* CLS on/off */
|
||||||
|
unsigned More : 1; /* More prompt */
|
||||||
|
unsigned FsMsged : 1; /* Fullscreen editor */
|
||||||
|
unsigned MailScan : 1; /* New Mail scan */
|
||||||
|
unsigned Guest : 1; /* Is guest account */
|
||||||
|
unsigned OL_ExtInfo : 1; /* OLR extended msg info */
|
||||||
|
int iTotalCalls; /* Total number of calls */
|
||||||
|
int iTimeLeft; /* Time left today */
|
||||||
|
int iConnectTime; /* Connect time this call */
|
||||||
|
int iTimeUsed; /* Time used today */
|
||||||
|
int iScreenLen; /* User Screen Length */
|
||||||
|
time_t tLastPwdChange; /* Date last password chg */
|
||||||
|
unsigned xHangUps;
|
||||||
|
long Credit; /* Users credit */
|
||||||
|
int Paged; /* Times paged today */
|
||||||
|
int xOfflineFmt;
|
||||||
|
int LastPktNum; /* Todays Last packet number*/
|
||||||
|
char Archiver[6]; /* Archiver to use */
|
||||||
|
|
||||||
|
int iLastFileArea; /* Number of last file area */
|
||||||
|
int iLastFileGroup; /* Number of last file group*/
|
||||||
|
char sProtocol[21]; /* Users default protocol */
|
||||||
|
unsigned long Downloads; /* Total number of d/l's */
|
||||||
|
unsigned long Uploads; /* Total number of uploads */
|
||||||
|
unsigned long UploadK; /* Upload KiloBytes */
|
||||||
|
unsigned long DownloadK; /* Download KiloBytes */
|
||||||
|
long DownloadKToday; /* KB Downloaded today */
|
||||||
|
long UploadKToday; /* KB Uploaded today */
|
||||||
|
int iTransferTime; /* Last file transfer time */
|
||||||
|
int iLastMsgArea; /* Number of last msg area */
|
||||||
|
int iLastMsgGroup; /* Number of last msg group */
|
||||||
|
int iPosted; /* Number of msgs posted */
|
||||||
|
int iLanguage; /* Current Language */
|
||||||
|
char sHandle[36]; /* Users Handle */
|
||||||
|
int iStatus; /* WhosDoingWhat status */
|
||||||
|
int DownloadsToday; /* Downloads today */
|
||||||
|
int CrtDef; /* IEMSI Terminal emulation */
|
||||||
|
int Protocol; /* IEMSI protocol */
|
||||||
|
unsigned IEMSI : 1; /* Is this a IEMSI session */
|
||||||
|
unsigned ieMNU : 1; /* Can do ASCII download */
|
||||||
|
unsigned ieTAB : 1; /* Can handle TAB character */
|
||||||
|
unsigned ieASCII8 : 1; /* Can handle 8-bit IBM-PC */
|
||||||
|
unsigned ieNEWS : 1; /* Show bulletins */
|
||||||
|
unsigned ieFILE : 1; /* Check for new files */
|
||||||
|
unsigned Email : 1; /* Has private email box */
|
||||||
|
unsigned FSemacs : 1; /* FSedit uses emacs keys */
|
||||||
|
char Password[Max_passlen+1];/* Plain password */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -5,7 +5,7 @@
|
|||||||
* Shadow Suite (c) ......: Julianne Frances Haugh
|
* Shadow Suite (c) ......: Julianne Frances Haugh
|
||||||
*
|
*
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
* Copyright (C) 1997-2001
|
* Copyright (C) 1997-2002
|
||||||
*
|
*
|
||||||
* Michiel Broek FIDO: 2:280/2802
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
* Beekmansbos 10
|
* Beekmansbos 10
|
||||||
@ -83,6 +83,7 @@ static int do_update_pwd = 0;
|
|||||||
|
|
||||||
|
|
||||||
#ifdef SHADOW_PASSWORD
|
#ifdef SHADOW_PASSWORD
|
||||||
|
static int is_shadow_pwd;
|
||||||
static void check_password(const struct passwd *, const struct spwd *);
|
static void check_password(const struct passwd *, const struct spwd *);
|
||||||
#else /* !SHADOW_PASSWORD */
|
#else /* !SHADOW_PASSWORD */
|
||||||
static void check_password(const struct passwd *);
|
static void check_password(const struct passwd *);
|
||||||
@ -124,7 +125,7 @@ static void fail_exit(int status)
|
|||||||
if (is_shadow_grp)
|
if (is_shadow_grp)
|
||||||
sgr_unlock();
|
sgr_unlock();
|
||||||
#endif
|
#endif
|
||||||
#ifdef SHADOWPWD
|
#ifdef SHADOW_PASSWORD
|
||||||
if (is_shadow_pwd)
|
if (is_shadow_pwd)
|
||||||
spw_unlock();
|
spw_unlock();
|
||||||
#endif
|
#endif
|
||||||
@ -319,7 +320,7 @@ int isexpired(const struct passwd *pw)
|
|||||||
* is considered to be infinite.
|
* is considered to be infinite.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SHADOWPWD
|
#ifdef SHADOW_PASSWORD
|
||||||
if (sp->sp_lstchg == -1 ||
|
if (sp->sp_lstchg == -1 ||
|
||||||
sp->sp_max == -1 || sp->sp_max >= (10000L*DAY/SCALE))
|
sp->sp_max == -1 || sp->sp_max >= (10000L*DAY/SCALE))
|
||||||
return 0;
|
return 0;
|
||||||
@ -335,7 +336,7 @@ int isexpired(const struct passwd *pw)
|
|||||||
* the password has expired.
|
* the password has expired.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SHADOWPWD
|
#ifdef SHADOW_PASSWORD
|
||||||
if (now >= sp->sp_lstchg + sp->sp_max)
|
if (now >= sp->sp_lstchg + sp->sp_max)
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
@ -778,8 +779,8 @@ int main(int argc, char *argv[])
|
|||||||
* this program runs under account mbse.
|
* this program runs under account mbse.
|
||||||
*/
|
*/
|
||||||
force = 1;
|
force = 1;
|
||||||
if (strcmp(pw->pw_name, (char *)"mbse")) {
|
if (strcmp(pw->pw_name, (char *)"mbse") && strcmp(pw->pw_name, (char *)"bbs")) {
|
||||||
fprintf(stderr, "mbpasswd: only user \"mbse\" may do this.\n");
|
fprintf(stderr, "mbpasswd: only users `mbse' and `bbs' may do this.\n");
|
||||||
exit(E_NOPERM);
|
exit(E_NOPERM);
|
||||||
}
|
}
|
||||||
} else if (strncmp(argv[1], "-n", 2) == 0) {
|
} else if (strncmp(argv[1], "-n", 2) == 0) {
|
||||||
@ -824,6 +825,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
|
|
||||||
#ifdef SHADOW_PASSWORD
|
#ifdef SHADOW_PASSWORD
|
||||||
|
is_shadow_pwd = spw_file_present();
|
||||||
|
|
||||||
sp = getspnam(name);
|
sp = getspnam(name);
|
||||||
if (!sp)
|
if (!sp)
|
||||||
sp = pwd_to_spwd(pw);
|
sp = pwd_to_spwd(pw);
|
||||||
|
575
mbsebbs/pwauth.c
Normal file
575
mbsebbs/pwauth.c
Normal file
@ -0,0 +1,575 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2002
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "pwauth.h"
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "encrypt.h"
|
||||||
|
|
||||||
|
#ifdef SKEY
|
||||||
|
#include <skey.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPIE
|
||||||
|
#include <opie.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __linux__ /* standard password prompt by default */
|
||||||
|
static const char *PROMPT = gettext_noop("Password: ");
|
||||||
|
#else
|
||||||
|
static const char *PROMPT = gettext_noop("%s's Password: ");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef AUTH_METHODS
|
||||||
|
/*
|
||||||
|
* Look-up table for bound-in methods. Put the name that the
|
||||||
|
* method is known by in the password field as "name" and a
|
||||||
|
* pointer to the function
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct method {
|
||||||
|
char *name;
|
||||||
|
int (*func) P_((const char *, int, const char *));
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef PAD_AUTH
|
||||||
|
int pad_auth();
|
||||||
|
#endif
|
||||||
|
static struct method methods[] = {
|
||||||
|
#ifdef PAD_AUTH
|
||||||
|
{ "pad", pad_auth },
|
||||||
|
#endif
|
||||||
|
{ "", 0 }
|
||||||
|
};
|
||||||
|
#endif /* AUTH_METHODS */
|
||||||
|
|
||||||
|
int wipe_clear_pass = 1;
|
||||||
|
char *clear_pass = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _old_auth - perform getpass/crypt authentication
|
||||||
|
*
|
||||||
|
* _old_auth gets the user's cleartext password and encrypts it
|
||||||
|
* using the salt in the encrypted password. The results are
|
||||||
|
* compared.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int _old_auth(const char *cipher, const char *user, int reason, const char *input)
|
||||||
|
{
|
||||||
|
char prompt[1024];
|
||||||
|
char *clear = NULL;
|
||||||
|
const char *cp;
|
||||||
|
int retval;
|
||||||
|
#ifdef SKEY
|
||||||
|
int use_skey = 0;
|
||||||
|
char challenge_info[40];
|
||||||
|
struct skey skey;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPIE
|
||||||
|
int use_opie = 0;
|
||||||
|
char o_challenge_info[OPIE_CHALLENGE_MAX + 1];
|
||||||
|
struct opie opie;
|
||||||
|
/*
|
||||||
|
* This implementation is based almost entirely on the SKEY code
|
||||||
|
* above. Thus the opie struct is called skey, etc. I am unaware
|
||||||
|
* if the system works at the same time, but I cannot imagine why
|
||||||
|
* anyone would want to do this....
|
||||||
|
* -- A.R.
|
||||||
|
* Mod: 5/14/98 A.R.
|
||||||
|
* Made the OPIE code separate from the S/Key code. Now
|
||||||
|
* (conceivably) both can be compiled in and function apart from
|
||||||
|
* one another (assuming a sysadmin really wants to maintain OPIE
|
||||||
|
* and an S/Key databases....).
|
||||||
|
*
|
||||||
|
* Also cleaned up the code a bit. Will be adding second-prompt
|
||||||
|
* support (the traditional Echo-on S/Key/OPIE-only prompts to let
|
||||||
|
* the users see the one-time passwords they are typing/pasting
|
||||||
|
* in....
|
||||||
|
* -- A.R.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are programs for adding and deleting authentication data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reason == PW_ADD || reason == PW_DELETE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* There are even programs for changing the user name ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reason == PW_CHANGE && input != (char *) 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING:
|
||||||
|
*
|
||||||
|
* When we change a password and we are root, we don't prompt.
|
||||||
|
* This is so root can change any password without having to
|
||||||
|
* know it. This is a policy decision that might have to be
|
||||||
|
* revisited.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reason == PW_CHANGE && getuid () == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WARNING:
|
||||||
|
*
|
||||||
|
* When we are logging in a user with no ciphertext password,
|
||||||
|
* we don't prompt for the password or anything. In reality
|
||||||
|
* the user could just hit <ENTER>, so it doesn't really
|
||||||
|
* matter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (cipher == (char *) 0 || *cipher == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef SKEY
|
||||||
|
/*
|
||||||
|
* If the user has an S/KEY entry show them the pertinent info
|
||||||
|
* and then we can try validating the created cyphertext and the SKEY.
|
||||||
|
* If there is no SKEY information we default to not using SKEY.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (skeychallenge (&skey, user, challenge_info) == 0)
|
||||||
|
use_skey = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPIE
|
||||||
|
/*
|
||||||
|
* Ditto above, for OPIE passwords.
|
||||||
|
* -- AR
|
||||||
|
*/
|
||||||
|
|
||||||
|
o_challenge_info[0] = '\0';
|
||||||
|
if (opiechallenge(&opie, user, o_challenge_info) == 0)
|
||||||
|
use_opie = 1;
|
||||||
|
|
||||||
|
if (use_opie == 0)
|
||||||
|
opieverify(&opie, (char *)NULL);
|
||||||
|
/*
|
||||||
|
* This call to opieverify is necessary within OPIE's interface:
|
||||||
|
* Every call to opiechallenge(), which checks to see if the user
|
||||||
|
* has an OPIE password, and if so get the challenge, must be
|
||||||
|
* accompanied by exactly one call to opieverify, which clears
|
||||||
|
* any outstanding locks, and otherwise cleans up.
|
||||||
|
* -- AR
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prompt for the password as required. FTPD and REXECD both
|
||||||
|
* get the cleartext password for us.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (reason != PW_FTP && reason != PW_REXEC && !input) {
|
||||||
|
if (! (cp = getdef_str ("LOGIN_STRING")))
|
||||||
|
cp = PROMPT;
|
||||||
|
#ifdef SKEY
|
||||||
|
if (use_skey)
|
||||||
|
printf ("[%s]\n", challenge_info);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPIE
|
||||||
|
if (use_opie)
|
||||||
|
printf("[ %s ]\n", o_challenge_info);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
snprintf(prompt, sizeof prompt, cp, user);
|
||||||
|
clear = getpass(prompt);
|
||||||
|
if (!clear) {
|
||||||
|
static char c[1];
|
||||||
|
c[0] = '\0';
|
||||||
|
clear = c;
|
||||||
|
}
|
||||||
|
input = clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert the cleartext password into a ciphertext string.
|
||||||
|
* If the two match, the return value will be zero, which is
|
||||||
|
* SUCCESS. Otherwise we see if SKEY is being used and check
|
||||||
|
* the results there as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
retval = strcmp(pw_encrypt(input, cipher), cipher);
|
||||||
|
|
||||||
|
#ifdef OPIE
|
||||||
|
/*
|
||||||
|
* This is required because using OPIE, opieverify() MUST be called
|
||||||
|
* opiechallenge() above even if OPIE isn't being used in this case,
|
||||||
|
* so locks get released, etc.
|
||||||
|
* -- AR
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((retval == 0) && use_opie)
|
||||||
|
opieverify(&opie, (char *)NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(SKEY) || defined(OPIE))
|
||||||
|
/*
|
||||||
|
* If (1) The password fails to match, and
|
||||||
|
* (2) The password is empty and
|
||||||
|
* (3) We are using OPIE or S/Key, then
|
||||||
|
* ...Re-prompt, with echo on.
|
||||||
|
* -- AR 8/22/1999
|
||||||
|
*/
|
||||||
|
if (retval && !input[0] &&
|
||||||
|
(0
|
||||||
|
#ifdef SKEY
|
||||||
|
|| use_skey
|
||||||
|
#endif
|
||||||
|
#ifdef OPIE
|
||||||
|
|| use_opie
|
||||||
|
#endif
|
||||||
|
)) {
|
||||||
|
strncat(prompt, _("(Echo on) "),
|
||||||
|
(sizeof(prompt) - strlen(prompt)));
|
||||||
|
clear = getpass_with_echo(prompt);
|
||||||
|
if (!clear) {
|
||||||
|
static char c[1];
|
||||||
|
c[0] = '\0';
|
||||||
|
clear = c;
|
||||||
|
}
|
||||||
|
input = clear;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SKEY
|
||||||
|
if (retval && use_skey) {
|
||||||
|
int passcheck = -1;
|
||||||
|
|
||||||
|
#if 0 /* some skey libs don't have skey_passcheck. --marekm */
|
||||||
|
passcheck = skey_passcheck(user, input);
|
||||||
|
#else
|
||||||
|
if (skeyverify(&skey, input) == 0)
|
||||||
|
passcheck = skey.n;
|
||||||
|
#endif /* if 0 */
|
||||||
|
if (passcheck > 0)
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef OPIE
|
||||||
|
if (retval && use_opie) {
|
||||||
|
if (opieverify(&opie, input) == 0)
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
#endif /* OPIE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Things like RADIUS authentication may need the password -
|
||||||
|
* if the external variable wipe_clear_pass is zero, we will
|
||||||
|
* not wipe it (the caller should wipe clear_pass when it is
|
||||||
|
* no longer needed). --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
clear_pass = clear;
|
||||||
|
if (wipe_clear_pass && clear && *clear)
|
||||||
|
strzero(clear);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef AUTH_METHODS
|
||||||
|
/*
|
||||||
|
* _pw_auth - perform alternate password authentication
|
||||||
|
*
|
||||||
|
* pw_auth executes the alternate password authentication method
|
||||||
|
* described in the user's password entry. _pw_auth does the real
|
||||||
|
* work, pw_auth splits the authentication string into individual
|
||||||
|
* command names.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int _pw_auth(const char *command, const char *user, int reason, const char *input)
|
||||||
|
{
|
||||||
|
RETSIGTYPE (*sigint)();
|
||||||
|
RETSIGTYPE (*sigquit)();
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
RETSIGTYPE (*sigtstp)();
|
||||||
|
#endif
|
||||||
|
int pid;
|
||||||
|
int status;
|
||||||
|
int i;
|
||||||
|
char * const argv[5];
|
||||||
|
int argc = 0;
|
||||||
|
int pipes[2];
|
||||||
|
char *empty_env = NULL;
|
||||||
|
int use_pipe;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Start with a quick sanity check. ALL command names must
|
||||||
|
* be fully-qualified path names.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (command[0] != '/')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the keyboard signals to be ignored. When the user kills
|
||||||
|
* the child we don't want the parent dying as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sigint = signal (SIGINT, SIG_IGN);
|
||||||
|
sigquit = signal (SIGQUIT, SIG_IGN);
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
sigtstp = signal (SIGTSTP, SIG_IGN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FTP and REXEC reasons don't give the program direct access
|
||||||
|
* to the user. This means that the program can only get input
|
||||||
|
* from this function. So we set up a pipe for that purpose.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use_pipe = (reason == PW_FTP || reason == PW_REXEC);
|
||||||
|
if (use_pipe)
|
||||||
|
if (pipe (pipes))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The program will be forked off with the parent process waiting
|
||||||
|
* on the child to tell it how successful it was.
|
||||||
|
*/
|
||||||
|
|
||||||
|
switch (pid = fork ()) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The fork() failed completely. Clean up as needed and
|
||||||
|
* return to the caller.
|
||||||
|
*/
|
||||||
|
case -1:
|
||||||
|
if (use_pipe) {
|
||||||
|
close (pipes[0]);
|
||||||
|
close (pipes[1]);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let the child catch the SIGINT and SIGQUIT
|
||||||
|
* signals. The parent, however, will continue
|
||||||
|
* to ignore them.
|
||||||
|
*/
|
||||||
|
signal (SIGINT, SIG_DFL);
|
||||||
|
signal (SIGQUIT, SIG_DFL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the command line. The first argument is
|
||||||
|
* the name of the command being executed. The
|
||||||
|
* second is the command line option for the reason,
|
||||||
|
* and the third is the user name.
|
||||||
|
*/
|
||||||
|
argv[argc++] = command;
|
||||||
|
switch (reason) {
|
||||||
|
case PW_SU: argv[argc++] = "-s"; break;
|
||||||
|
case PW_LOGIN: argv[argc++] = "-l"; break;
|
||||||
|
case PW_ADD: argv[argc++] = "-a"; break;
|
||||||
|
case PW_CHANGE: argv[argc++] = "-c"; break;
|
||||||
|
case PW_DELETE: argv[argc++] = "-d"; break;
|
||||||
|
case PW_TELNET: argv[argc++] = "-t"; break;
|
||||||
|
case PW_RLOGIN: argv[argc++] = "-r"; break;
|
||||||
|
case PW_FTP: argv[argc++] = "-f"; break;
|
||||||
|
case PW_REXEC: argv[argc++] = "-x"; break;
|
||||||
|
}
|
||||||
|
if (reason == PW_CHANGE && input)
|
||||||
|
argv[argc++] = input;
|
||||||
|
|
||||||
|
argv[argc++] = user;
|
||||||
|
argv[argc] = (char *) 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The FTP and REXEC reasons use a pipe to communicate
|
||||||
|
* with the parent. The other standard I/O descriptors
|
||||||
|
* are closed and re-opened as /dev/null.
|
||||||
|
*/
|
||||||
|
if (use_pipe) {
|
||||||
|
close (0);
|
||||||
|
close (1);
|
||||||
|
close (2);
|
||||||
|
|
||||||
|
if (dup (pipes[0]) != 0)
|
||||||
|
exit (1);
|
||||||
|
|
||||||
|
close (pipes[0]);
|
||||||
|
close (pipes[1]);
|
||||||
|
|
||||||
|
if (open ("/dev/null", O_WRONLY) != 1)
|
||||||
|
exit (1);
|
||||||
|
|
||||||
|
if (open ("/dev/null", O_WRONLY) != 2)
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now we execute the command directly.
|
||||||
|
* Do it with empty environment for safety. --marekm
|
||||||
|
*/
|
||||||
|
execve(command, argv, &empty_env);
|
||||||
|
_exit((errno == ENOENT) ? 127 : 126);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* FTP and REXEC cause a single line of text to be
|
||||||
|
* sent to the child over a pipe that was set up
|
||||||
|
* earlier.
|
||||||
|
*/
|
||||||
|
if (use_pipe) {
|
||||||
|
close (pipes[0]);
|
||||||
|
|
||||||
|
if (input)
|
||||||
|
write (pipes[1], input, strlen (input));
|
||||||
|
|
||||||
|
write (pipes[1], "\n", 1);
|
||||||
|
close (pipes[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait on the child to die. When it does you will
|
||||||
|
* get the exit status and use that to determine if
|
||||||
|
* the authentication program was successful.
|
||||||
|
*/
|
||||||
|
while ((i = wait (&status)) != pid && i != -1)
|
||||||
|
;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Re-set the signals to their earlier values.
|
||||||
|
*/
|
||||||
|
signal (SIGINT, sigint);
|
||||||
|
signal (SIGQUIT, sigquit);
|
||||||
|
#ifdef SIGTSTP
|
||||||
|
signal (SIGTSTP, sigtstp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure we found the right process!
|
||||||
|
*/
|
||||||
|
if (i == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (status == 0)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _builtin_auth - lookup routine in table and execute
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int _builtin_auth(const char *command, const char *user, int reason, const char *input)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan the table, looking for a match. If we fall off
|
||||||
|
* the end, it must mean that this method isn't supported,
|
||||||
|
* so we fail the authentication.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i = 0;methods[i].name[0];i++) {
|
||||||
|
if (! strcmp (command, methods[i].name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (methods[i].name[0] == '\0')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call the pointed to function with the other three
|
||||||
|
* arguments.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return (methods[i].func) (user, reason, input);
|
||||||
|
}
|
||||||
|
#endif /* AUTH_METHODS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function does the real work. It splits the list of program names
|
||||||
|
* up into individual programs and executes them one at a time.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int pw_auth(const char *command, const char *user, int reason, const char *input)
|
||||||
|
{
|
||||||
|
#ifdef AUTH_METHODS
|
||||||
|
char buf[256];
|
||||||
|
char *cmd, *end;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quick little sanity check ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (strlen (command) >= sizeof buf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
strcpy(buf, command); /* safe (because of the above check) --marekm */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find each command and make sure it is NUL-terminated. Then
|
||||||
|
* invoke _pw_auth to actually run the program. The first
|
||||||
|
* failing program ends the whole mess.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (cmd = buf;cmd;cmd = end) {
|
||||||
|
if ((end = strchr (cmd, ';')))
|
||||||
|
*end++ = '\0';
|
||||||
|
|
||||||
|
if (cmd[0] != '@')
|
||||||
|
rc = _old_auth (cmd, user, reason, input);
|
||||||
|
else if (cmd[1] == '/')
|
||||||
|
rc = _pw_auth (cmd + 1, user, reason, input);
|
||||||
|
else
|
||||||
|
rc = _builtin_auth (cmd + 1, user, reason, input);
|
||||||
|
if (rc)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return _old_auth(command, user, reason, input);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
31
mbsebbs/pwauth.h
Normal file
31
mbsebbs/pwauth.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _PWAUTH_H
|
||||||
|
#define _PWAUTH_H
|
||||||
|
|
||||||
|
int pw_auth(const char *program,const char *user,int flag,const char *input);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local access
|
||||||
|
*/
|
||||||
|
#define PW_SU 1
|
||||||
|
#define PW_LOGIN 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Administrative functions
|
||||||
|
*/
|
||||||
|
#define PW_ADD 101
|
||||||
|
#define PW_CHANGE 102
|
||||||
|
#define PW_DELETE 103
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Network access
|
||||||
|
*/
|
||||||
|
#define PW_TELNET 201
|
||||||
|
#define PW_RLOGIN 202
|
||||||
|
#define PW_FTP 203
|
||||||
|
#define PW_REXEC 204
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
98
mbsebbs/pwdcheck.c
Normal file
98
mbsebbs/pwdcheck.c
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include "pwauth.h"
|
||||||
|
#include "pwdcheck.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SHADOW_H
|
||||||
|
#include <shadow.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_PAM
|
||||||
|
// #include "pam_defs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WRONGPWD2 "incorrect password for `%s'"
|
||||||
|
|
||||||
|
void passwd_check(const char *user, const char *passwd, const char *progname)
|
||||||
|
{
|
||||||
|
#ifdef USE_PAM
|
||||||
|
pam_handle_t *pamh = NULL;
|
||||||
|
int retcode;
|
||||||
|
struct pam_conv conv = { misc_conv, NULL };
|
||||||
|
|
||||||
|
if (pam_start(progname, user, &conv, &pamh)) {
|
||||||
|
bailout:
|
||||||
|
SYSLOG((LOG_WARN, WRONGPWD2, user));
|
||||||
|
sleep(1);
|
||||||
|
fprintf(stderr, "Incorrect password for %s.\n", user);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (pam_authenticate(pamh, 0))
|
||||||
|
goto bailout;
|
||||||
|
|
||||||
|
retcode = pam_acct_mgmt(pamh, 0);
|
||||||
|
if (retcode == PAM_NEW_AUTHTOK_REQD) {
|
||||||
|
retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
|
||||||
|
} else if (retcode)
|
||||||
|
goto bailout;
|
||||||
|
|
||||||
|
if (pam_setcred(pamh, 0))
|
||||||
|
goto bailout;
|
||||||
|
|
||||||
|
/* no need to establish a session; this isn't a session-oriented
|
||||||
|
* activity... */
|
||||||
|
|
||||||
|
#else /* !USE_PAM */
|
||||||
|
|
||||||
|
#ifdef SHADOW_PASSWORD
|
||||||
|
struct spwd *sp;
|
||||||
|
|
||||||
|
if ((sp = getspnam(user)))
|
||||||
|
passwd = sp->sp_pwdp;
|
||||||
|
endspent();
|
||||||
|
#endif
|
||||||
|
if (pw_auth(passwd, user, PW_LOGIN, (char *) 0) != 0) {
|
||||||
|
syslog(LOG_WARNING, WRONGPWD2, user);
|
||||||
|
sleep(1);
|
||||||
|
fprintf(stderr, "Incorrect password for %s.\n", user);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif /* !USE_PAM */
|
||||||
|
}
|
||||||
|
|
8
mbsebbs/pwdcheck.h
Normal file
8
mbsebbs/pwdcheck.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _PWDCHECK_H
|
||||||
|
#define _PWDCHECK_H
|
||||||
|
|
||||||
|
void passwd_check(const char *, const char *, const char *);
|
||||||
|
|
||||||
|
#endif
|
127
mbsebbs/setugid.c
Normal file
127
mbsebbs/setugid.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Separated from setup.c. --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <pwd.h>
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "setugid.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup_uid_gid() split in two functions for PAM support -
|
||||||
|
* pam_setcred() needs to be called after initgroups(), but
|
||||||
|
* before setuid().
|
||||||
|
*/
|
||||||
|
|
||||||
|
int setup_groups(const struct passwd *info)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set the real group ID to the primary group ID in the password
|
||||||
|
* file.
|
||||||
|
*/
|
||||||
|
if (setgid (info->pw_gid) == -1) {
|
||||||
|
perror("setgid");
|
||||||
|
syslog(LOG_ERR, "bad group ID `%d' for user `%s': %m\n", info->pw_gid, info->pw_name);
|
||||||
|
closelog();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_INITGROUPS
|
||||||
|
/*
|
||||||
|
* For systems which support multiple concurrent groups, go get
|
||||||
|
* the group set from the /etc/group file.
|
||||||
|
*/
|
||||||
|
if (initgroups(info->pw_name, info->pw_gid) == -1) {
|
||||||
|
perror("initgroups");
|
||||||
|
syslog(LOG_ERR, "initgroups failed for user `%s': %m\n", info->pw_name);
|
||||||
|
closelog();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int change_uid(const struct passwd *info)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Set the real UID to the UID value in the password file.
|
||||||
|
*/
|
||||||
|
#ifndef BSD
|
||||||
|
if (setuid(info->pw_uid))
|
||||||
|
#else
|
||||||
|
if (setreuid(info->pw_uid, info->pw_uid))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
perror("setuid");
|
||||||
|
syslog(LOG_ERR, "bad user ID `%d' for user `%s': %m\n", (int) info->pw_uid, info->pw_name);
|
||||||
|
closelog();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup_uid_gid() performs the following steps -
|
||||||
|
*
|
||||||
|
* set the group ID to the value from the password file entry
|
||||||
|
* set the supplementary group IDs
|
||||||
|
* optionally call specified function which may add more groups
|
||||||
|
* set the user ID to the value from the password file entry
|
||||||
|
*
|
||||||
|
* Returns 0 on success, or -1 on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int setup_uid_gid(const struct passwd *info, int is_console)
|
||||||
|
{
|
||||||
|
if (setup_groups(info) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#ifdef HAVE_INITGROUPS
|
||||||
|
if (is_console) {
|
||||||
|
char *cp = getdef_str("CONSOLE_GROUPS");
|
||||||
|
if (cp && add_groups(cp))
|
||||||
|
perror("Warning: add_groups");
|
||||||
|
}
|
||||||
|
#endif /* HAVE_INITGROUPS */
|
||||||
|
|
||||||
|
if (change_uid(info) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
10
mbsebbs/setugid.h
Normal file
10
mbsebbs/setugid.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _SETUGID_H
|
||||||
|
#define _SETUGID_H
|
||||||
|
|
||||||
|
int setup_groups(const struct passwd *);
|
||||||
|
int change_uid(const struct passwd *);
|
||||||
|
int setup_uid_gid(const struct passwd *, int);
|
||||||
|
|
||||||
|
#endif
|
275
mbsebbs/setupenv.c
Normal file
275
mbsebbs/setupenv.c
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Separated from setup.c. --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <pwd.h>
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "env.h"
|
||||||
|
#include "setupenv.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void addenv_path(const char *varname, const char *dirname, const char *filename)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
buf = xmalloc(strlen(dirname) + strlen(filename) + 2);
|
||||||
|
sprintf(buf, "%s/%s", dirname, filename);
|
||||||
|
addenv(varname, buf);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void read_env_file(const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char buf[1024];
|
||||||
|
char *cp, *name, *val;
|
||||||
|
|
||||||
|
fp = fopen(filename, "r");
|
||||||
|
if (!fp)
|
||||||
|
return;
|
||||||
|
while (fgets(buf, sizeof buf, fp) == buf) {
|
||||||
|
cp = strrchr(buf, '\n');
|
||||||
|
if (!cp)
|
||||||
|
break;
|
||||||
|
*cp = '\0';
|
||||||
|
|
||||||
|
cp = buf;
|
||||||
|
/* ignore whitespace and comments */
|
||||||
|
while (*cp && isspace(*cp))
|
||||||
|
cp++;
|
||||||
|
if (*cp == '\0' || *cp == '#')
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* ignore lines which don't follow the name=value format
|
||||||
|
* (for example, the "export NAME" shell commands)
|
||||||
|
*/
|
||||||
|
name = cp;
|
||||||
|
while (*cp && !isspace(*cp) && *cp != '=')
|
||||||
|
cp++;
|
||||||
|
if (*cp != '=')
|
||||||
|
continue;
|
||||||
|
/* NUL-terminate the name */
|
||||||
|
*cp++ = '\0';
|
||||||
|
val = cp;
|
||||||
|
#if 0 /* XXX untested, and needs rewrite with fewer goto's :-) */
|
||||||
|
/*
|
||||||
|
(state, char_type) -> (state, action)
|
||||||
|
|
||||||
|
state: unquoted, single_quoted, double_quoted, escaped, double_quoted_escaped
|
||||||
|
char_type: normal, white, backslash, single, double
|
||||||
|
action: remove_curr, remove_curr_skip_next, remove_prev, finish XXX
|
||||||
|
*/
|
||||||
|
no_quote:
|
||||||
|
if (*cp == '\\') {
|
||||||
|
/* remove the backslash */
|
||||||
|
remove_char(cp);
|
||||||
|
/* skip over the next character */
|
||||||
|
if (*cp)
|
||||||
|
cp++;
|
||||||
|
goto no_quote;
|
||||||
|
} else if (*cp == '\'') {
|
||||||
|
/* remove the quote */
|
||||||
|
remove_char(cp);
|
||||||
|
/* now within single quotes */
|
||||||
|
goto s_quote;
|
||||||
|
} else if (*cp == '"') {
|
||||||
|
/* remove the quote */
|
||||||
|
remove_char(cp);
|
||||||
|
/* now within double quotes */
|
||||||
|
goto d_quote;
|
||||||
|
} else if (*cp == '\0') {
|
||||||
|
/* end of string */
|
||||||
|
goto finished;
|
||||||
|
} else if (isspace(*cp)) {
|
||||||
|
/* unescaped whitespace - end of string */
|
||||||
|
*cp = '\0';
|
||||||
|
goto finished;
|
||||||
|
} else {
|
||||||
|
cp++;
|
||||||
|
goto no_quote;
|
||||||
|
}
|
||||||
|
s_quote:
|
||||||
|
if (*cp == '\'') {
|
||||||
|
/* remove the quote */
|
||||||
|
remove_char(cp);
|
||||||
|
/* unquoted again */
|
||||||
|
goto no_quote;
|
||||||
|
} else if (*cp == '\0') {
|
||||||
|
/* end of string */
|
||||||
|
goto finished;
|
||||||
|
} else {
|
||||||
|
/* preserve everything within single quotes */
|
||||||
|
cp++;
|
||||||
|
goto s_quote;
|
||||||
|
}
|
||||||
|
d_quote:
|
||||||
|
if (*cp == '\"') {
|
||||||
|
/* remove the quote */
|
||||||
|
remove_char(cp);
|
||||||
|
/* unquoted again */
|
||||||
|
goto no_quote;
|
||||||
|
} else if (*cp == '\\') {
|
||||||
|
cp++;
|
||||||
|
/* if backslash followed by double quote, remove backslash
|
||||||
|
else skip over the backslash and following char */
|
||||||
|
if (*cp == '"')
|
||||||
|
remove_char(cp - 1);
|
||||||
|
else if (*cp)
|
||||||
|
cp++;
|
||||||
|
goto d_quote;
|
||||||
|
} eise if (*cp == '\0') {
|
||||||
|
/* end of string */
|
||||||
|
goto finished;
|
||||||
|
} else {
|
||||||
|
/* preserve everything within double quotes */
|
||||||
|
goto d_quote;
|
||||||
|
}
|
||||||
|
finished:
|
||||||
|
#endif /* 0 */
|
||||||
|
/*
|
||||||
|
* XXX - should handle quotes, backslash escapes, etc.
|
||||||
|
* like the shell does.
|
||||||
|
*/
|
||||||
|
addenv(name, val);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* change to the user's home directory
|
||||||
|
* set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
|
||||||
|
* variables.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setup_env(struct passwd *info)
|
||||||
|
{
|
||||||
|
char *cp, *envf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change the current working directory to be the home directory
|
||||||
|
* of the user. It is a fatal error for this process to be unable
|
||||||
|
* to change to that directory. There is no "default" home
|
||||||
|
* directory.
|
||||||
|
*
|
||||||
|
* We no longer do it as root - should work better on NFS-mounted
|
||||||
|
* home directories. Some systems default to HOME=/, so we make
|
||||||
|
* this a configurable option. --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (chdir(info->pw_dir) == -1) {
|
||||||
|
static char temp_pw_dir[] = "/";
|
||||||
|
if (!getdef_bool("DEFAULT_HOME") || chdir("/") == -1) {
|
||||||
|
fprintf(stderr, _("Unable to cd to \"%s\"\n"), info->pw_dir);
|
||||||
|
syslog(LOG_WARNING, "unable to cd to `%s' for user `%s'\n", info->pw_dir, info->pw_name);
|
||||||
|
closelog();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
puts(_("No directory, logging in with HOME=/"));
|
||||||
|
info->pw_dir = temp_pw_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the HOME environmental variable and export it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
addenv("HOME", info->pw_dir);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the SHELL environmental variable and export it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (info->pw_shell == (char *) 0 || ! *info->pw_shell) {
|
||||||
|
static char temp_pw_shell[] = "/bin/sh";
|
||||||
|
info->pw_shell = temp_pw_shell;
|
||||||
|
}
|
||||||
|
|
||||||
|
addenv("SHELL", info->pw_shell);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the PATH environmental variable and export it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cp = getdef_str( info->pw_uid == 0 ? "ENV_SUPATH" : "ENV_PATH" );
|
||||||
|
addenv(cp ? cp : "PATH=/bin:/usr/bin", NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Export the user name. For BSD derived systems, it's "USER", for
|
||||||
|
* all others it's "LOGNAME". We set both of them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
addenv("USER", info->pw_name);
|
||||||
|
addenv("LOGNAME", info->pw_name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MAILDIR environment variable for Qmail
|
||||||
|
*/
|
||||||
|
if ((cp=getdef_str("QMAIL_DIR")))
|
||||||
|
addenv_path("MAILDIR", info->pw_dir, cp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the MAIL environmental variable and export it. login.defs
|
||||||
|
* knows the prefix.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((cp=getdef_str("MAIL_DIR")))
|
||||||
|
addenv_path("MAIL", cp, info->pw_name);
|
||||||
|
else if ((cp=getdef_str("MAIL_FILE")))
|
||||||
|
addenv_path("MAIL", info->pw_dir, cp);
|
||||||
|
else {
|
||||||
|
#if defined(MAIL_SPOOL_FILE)
|
||||||
|
addenv_path("MAIL", info->pw_dir, MAIL_SPOOL_FILE);
|
||||||
|
#elif defined(MAIL_SPOOL_DIR)
|
||||||
|
addenv_path("MAIL", MAIL_SPOOL_DIR, info->pw_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read environment from optional config file. --marekm
|
||||||
|
*/
|
||||||
|
if ((envf = getdef_str("ENVIRON_FILE")))
|
||||||
|
read_env_file(envf);
|
||||||
|
}
|
10
mbsebbs/setupenv.h
Normal file
10
mbsebbs/setupenv.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _SETUPENV_H
|
||||||
|
#define _SETUPENV_H
|
||||||
|
|
||||||
|
void addenv_path(const char *, const char *, const char *);
|
||||||
|
void read_env_file(const char *);
|
||||||
|
void setup_env(struct passwd *);
|
||||||
|
|
||||||
|
#endif
|
128
mbsebbs/shell.c
Normal file
128
mbsebbs/shell.c
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "basename.h"
|
||||||
|
#include "shell.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern char **newenvp;
|
||||||
|
extern size_t newenvc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* shell - execute the named program
|
||||||
|
*
|
||||||
|
* shell begins by trying to figure out what argv[0] is going to
|
||||||
|
* be for the named process. The user may pass in that argument,
|
||||||
|
* or it will be the last pathname component of the file with a
|
||||||
|
* '-' prepended. The first attempt is to just execute the named
|
||||||
|
* file. If the errno comes back "ENOEXEC", the file is assumed
|
||||||
|
* at first glance to be a shell script. The first two characters
|
||||||
|
* must be "#!", in which case "/bin/sh" is executed to process
|
||||||
|
* the file. If all that fails, give up in disgust ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
void shell(const char *file, const char *arg)
|
||||||
|
{
|
||||||
|
char arg0[1024];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (file == (char *) 0)
|
||||||
|
exit (1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The argv[0]'th entry is usually the path name, but
|
||||||
|
* for various reasons the invoker may want to override
|
||||||
|
* that. So, we determine the 0'th entry only if they
|
||||||
|
* don't want to tell us what it is themselves.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (arg == (char *) 0) {
|
||||||
|
snprintf(arg0, sizeof arg0, "-%s", Basename((char *) file));
|
||||||
|
arg = arg0;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf (_("Executing shell %s\n"), file);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First we try the direct approach. The system should be
|
||||||
|
* able to figure out what we are up to without too much
|
||||||
|
* grief.
|
||||||
|
*/
|
||||||
|
|
||||||
|
execle (file, arg, (char *) 0, newenvp);
|
||||||
|
err = errno;
|
||||||
|
|
||||||
|
/* Linux handles #! in the kernel, and bash doesn't make
|
||||||
|
sense of "#!" so it wouldn't work anyway... --marekm */
|
||||||
|
#ifndef __linux__
|
||||||
|
/*
|
||||||
|
* It is perfectly OK to have a shell script for a login
|
||||||
|
* shell, and this code attempts to support that. It
|
||||||
|
* relies on the standard shell being able to make sense
|
||||||
|
* of the "#!" magic number.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (err == ENOEXEC) {
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
if ((fp = fopen (file, "r"))) {
|
||||||
|
if (getc (fp) == '#' && getc (fp) == '!') {
|
||||||
|
fclose (fp);
|
||||||
|
execle ("/bin/sh", "sh",
|
||||||
|
file, (char *) 0, newenvp);
|
||||||
|
err = errno;
|
||||||
|
} else {
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obviously something is really wrong - I can't figure out
|
||||||
|
* how to execute this stupid shell, so I might as well give
|
||||||
|
* up in disgust ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
snprintf(arg0, sizeof arg0, "Cannot execute %s", file);
|
||||||
|
errno = err;
|
||||||
|
perror(arg0);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
8
mbsebbs/shell.h
Normal file
8
mbsebbs/shell.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _SHELL_H
|
||||||
|
#define _SHELL_H
|
||||||
|
|
||||||
|
void shell(const char *, const char *);
|
||||||
|
|
||||||
|
#endif
|
292
mbsebbs/snprintf.c
Normal file
292
mbsebbs/snprintf.c
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
/**************************************************************
|
||||||
|
* Original:
|
||||||
|
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
|
||||||
|
* A bombproof version of doprnt (dopr) included.
|
||||||
|
* Sigh. This sort of thing is always nasty do deal with. Note that
|
||||||
|
* the version here does not include floating point...
|
||||||
|
*
|
||||||
|
* snprintf() is used instead of sprintf() as it does limit checks
|
||||||
|
* for string length. This covers a nasty loophole.
|
||||||
|
*
|
||||||
|
* The other functions are there to prevent NULL pointers from
|
||||||
|
* causing nast effects.
|
||||||
|
**************************************************************/
|
||||||
|
|
||||||
|
/* $XFree86: xc/lib/misc/snprintf.c,v 3.0 1996/08/26 06:19:23 dawes Exp $ */
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "snprintf.h"
|
||||||
|
|
||||||
|
static void dopr(char *, char *, va_list);
|
||||||
|
static char *end;
|
||||||
|
|
||||||
|
/* varargs declarations: */
|
||||||
|
|
||||||
|
#if defined(HAVE_STDARG_H)
|
||||||
|
# include <stdarg.h>
|
||||||
|
# define HAVE_STDARGS /* let's hope that works everywhere (mj) */
|
||||||
|
# define VA_LOCAL_DECL va_list ap;
|
||||||
|
# define VA_START(f) va_start(ap, f)
|
||||||
|
# define VA_SHIFT(v,t) ; /* no-op for ANSI */
|
||||||
|
# define VA_END va_end(ap)
|
||||||
|
#else
|
||||||
|
# if defined(HAVE_VARARGS_H)
|
||||||
|
# include <varargs.h>
|
||||||
|
# undef HAVE_STDARGS
|
||||||
|
# define VA_LOCAL_DECL va_list ap;
|
||||||
|
# define VA_START(f) va_start(ap) /* f is ignored! */
|
||||||
|
# define VA_SHIFT(v,t) v = va_arg(ap,t)
|
||||||
|
# define VA_END va_end(ap)
|
||||||
|
# else
|
||||||
|
/*XX ** NO VARARGS ** XX*/
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STDARGS
|
||||||
|
int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||||
|
int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||||
|
#else
|
||||||
|
int snprintf ();
|
||||||
|
int vsnprintf ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int vsnprintf(char *str, size_t count, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
str[0] = 0;
|
||||||
|
end = str+count-1;
|
||||||
|
dopr( str, fmt, args );
|
||||||
|
if( count>0 ){
|
||||||
|
end[0] = 0;
|
||||||
|
}
|
||||||
|
return(strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VARARGS3 */
|
||||||
|
#ifdef HAVE_STDARGS
|
||||||
|
int
|
||||||
|
snprintf (char *str,size_t count,const char *fmt,...)
|
||||||
|
#else
|
||||||
|
int
|
||||||
|
snprintf (va_alist) va_dcl
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#ifndef HAVE_STDARGS
|
||||||
|
char *str;
|
||||||
|
size_t count;
|
||||||
|
char *fmt;
|
||||||
|
#endif
|
||||||
|
VA_LOCAL_DECL
|
||||||
|
|
||||||
|
VA_START (fmt);
|
||||||
|
VA_SHIFT (str, char *);
|
||||||
|
VA_SHIFT (count, size_t );
|
||||||
|
VA_SHIFT (fmt, char *);
|
||||||
|
(void) vsnprintf ( str, count, fmt, ap);
|
||||||
|
VA_END;
|
||||||
|
return( strlen( str ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dopr(): poor man's version of doprintf
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void fmtstr(char *value, int ljust, int len, int zpad);
|
||||||
|
static void fmtnum(long value, int base, int dosign, int ljust, int len, int zpad);
|
||||||
|
static void dostr(char *);
|
||||||
|
static char *output;
|
||||||
|
static void dopr_outch(int c);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void dopr(char *buffer, char *format, va_list args)
|
||||||
|
{
|
||||||
|
int ch;
|
||||||
|
long value;
|
||||||
|
int longflag = 0;
|
||||||
|
char *strvalue;
|
||||||
|
int ljust;
|
||||||
|
int len;
|
||||||
|
int zpad;
|
||||||
|
|
||||||
|
output = buffer;
|
||||||
|
while( (ch = *format++) ){
|
||||||
|
switch( ch ){
|
||||||
|
case '%':
|
||||||
|
ljust = len = zpad = 0;
|
||||||
|
nextch:
|
||||||
|
ch = *format++;
|
||||||
|
switch( ch ){
|
||||||
|
case 0:
|
||||||
|
dostr((char *)"**end of format**");
|
||||||
|
return;
|
||||||
|
case '-': ljust = 1; goto nextch;
|
||||||
|
case '0': /* set zero padding if len not set */
|
||||||
|
if(len==0) zpad = '0';
|
||||||
|
case '1': case '2': case '3':
|
||||||
|
case '4': case '5': case '6':
|
||||||
|
case '7': case '8': case '9':
|
||||||
|
len = len*10 + ch - '0';
|
||||||
|
goto nextch;
|
||||||
|
case 'l': longflag = 1; goto nextch;
|
||||||
|
case 'u': case 'U':
|
||||||
|
/*fmtnum(value,base,dosign,ljust,len,zpad) */
|
||||||
|
if( longflag ){
|
||||||
|
value = va_arg( args, long );
|
||||||
|
} else {
|
||||||
|
value = va_arg( args, int );
|
||||||
|
}
|
||||||
|
fmtnum( value, 10,0, ljust, len, zpad ); break;
|
||||||
|
case 'o': case 'O':
|
||||||
|
/*fmtnum(value,base,dosign,ljust,len,zpad) */
|
||||||
|
if( longflag ){
|
||||||
|
value = va_arg( args, long );
|
||||||
|
} else {
|
||||||
|
value = va_arg( args, int );
|
||||||
|
}
|
||||||
|
fmtnum( value, 8,0, ljust, len, zpad ); break;
|
||||||
|
case 'd': case 'D':
|
||||||
|
if( longflag ){
|
||||||
|
value = va_arg( args, long );
|
||||||
|
} else {
|
||||||
|
value = va_arg( args, int );
|
||||||
|
}
|
||||||
|
fmtnum( value, 10,1, ljust, len, zpad ); break;
|
||||||
|
case 'x':
|
||||||
|
if( longflag ){
|
||||||
|
value = va_arg( args, long );
|
||||||
|
} else {
|
||||||
|
value = va_arg( args, int );
|
||||||
|
}
|
||||||
|
fmtnum( value, 16,0, ljust, len, zpad ); break;
|
||||||
|
case 'X':
|
||||||
|
if( longflag ){
|
||||||
|
value = va_arg( args, long );
|
||||||
|
} else {
|
||||||
|
value = va_arg( args, int );
|
||||||
|
}
|
||||||
|
fmtnum( value,-16,0, ljust, len, zpad ); break;
|
||||||
|
case 's':
|
||||||
|
strvalue = va_arg( args, char *);
|
||||||
|
fmtstr( strvalue,ljust,len,zpad ); break;
|
||||||
|
case 'c':
|
||||||
|
ch = va_arg( args, int );
|
||||||
|
dopr_outch( ch ); break;
|
||||||
|
case '%': dopr_outch( ch ); continue;
|
||||||
|
default:
|
||||||
|
dostr((char *)"???????");
|
||||||
|
}
|
||||||
|
longflag = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dopr_outch( ch );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*output = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fmtstr(char *value, int ljust, int len, int zpad)
|
||||||
|
{
|
||||||
|
int padlen, lstrlen; /* amount to pad */
|
||||||
|
|
||||||
|
if( value == 0 ){
|
||||||
|
value = (char *)"<NULL>";
|
||||||
|
}
|
||||||
|
for( lstrlen = 0; value[lstrlen]; ++ lstrlen ); /* strlen */
|
||||||
|
padlen = len - lstrlen;
|
||||||
|
if( padlen < 0 ) padlen = 0;
|
||||||
|
if( ljust ) padlen = -padlen;
|
||||||
|
while( padlen > 0 ) {
|
||||||
|
dopr_outch( ' ' );
|
||||||
|
--padlen;
|
||||||
|
}
|
||||||
|
dostr( value );
|
||||||
|
while( padlen < 0 ) {
|
||||||
|
dopr_outch( ' ' );
|
||||||
|
++padlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void fmtnum(long value, int base, int dosign, int ljust, int len, int zpad)
|
||||||
|
{
|
||||||
|
int signvalue = 0;
|
||||||
|
unsigned long uvalue;
|
||||||
|
char convert[20];
|
||||||
|
int place = 0;
|
||||||
|
int padlen = 0; /* amount to pad */
|
||||||
|
int caps = 0;
|
||||||
|
|
||||||
|
/* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
|
||||||
|
value, base, dosign, ljust, len, zpad )); */
|
||||||
|
uvalue = value;
|
||||||
|
if( dosign ){
|
||||||
|
if( value < 0 ) {
|
||||||
|
signvalue = '-';
|
||||||
|
uvalue = -value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( base < 0 ){
|
||||||
|
caps = 1;
|
||||||
|
base = -base;
|
||||||
|
}
|
||||||
|
do{
|
||||||
|
convert[place++] =
|
||||||
|
(caps? "0123456789ABCDEF":"0123456789abcdef")
|
||||||
|
[uvalue % (unsigned)base ];
|
||||||
|
uvalue = (uvalue / (unsigned)base );
|
||||||
|
}while(uvalue);
|
||||||
|
convert[place] = 0;
|
||||||
|
padlen = len - place;
|
||||||
|
if( padlen < 0 ) padlen = 0;
|
||||||
|
if( ljust ) padlen = -padlen;
|
||||||
|
/* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
|
||||||
|
convert,place,signvalue,padlen)); */
|
||||||
|
if( zpad && padlen > 0 ){
|
||||||
|
if( signvalue ){
|
||||||
|
dopr_outch( signvalue );
|
||||||
|
--padlen;
|
||||||
|
signvalue = 0;
|
||||||
|
}
|
||||||
|
while( padlen > 0 ){
|
||||||
|
dopr_outch( zpad );
|
||||||
|
--padlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while( padlen > 0 ) {
|
||||||
|
dopr_outch( ' ' );
|
||||||
|
--padlen;
|
||||||
|
}
|
||||||
|
if( signvalue ) dopr_outch( signvalue );
|
||||||
|
while( place > 0 ) dopr_outch( convert[--place] );
|
||||||
|
while( padlen < 0 ){
|
||||||
|
dopr_outch( ' ' );
|
||||||
|
++padlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void dostr(char *str)
|
||||||
|
{
|
||||||
|
while(*str) dopr_outch(*str++);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void dopr_outch(int c)
|
||||||
|
{
|
||||||
|
if( iscntrl(c) && c != '\n' && c != '\t' ){
|
||||||
|
c = '@' + (c & 0x1F);
|
||||||
|
if( end == 0 || output < end ){
|
||||||
|
*output++ = '^';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( end == 0 || output < end ){
|
||||||
|
*output++ = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
51
mbsebbs/snprintf.h
Normal file
51
mbsebbs/snprintf.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/* $XFree86: xc/lib/misc/snprintf.h,v 3.1 1996/08/26 14:42:33 dawes Exp $ */
|
||||||
|
|
||||||
|
#ifndef SNPRINTF_H
|
||||||
|
#define SNPRINTF_H
|
||||||
|
|
||||||
|
#ifdef HAS_SNPRINTF
|
||||||
|
#ifdef LIBXT
|
||||||
|
#define _XtSnprintf snprintf
|
||||||
|
#define _XtVsnprintf vsnprintf
|
||||||
|
#endif
|
||||||
|
#ifdef LIBX11
|
||||||
|
#define _XSnprintf snprintf
|
||||||
|
#define _XVsnprintf vsnprintf
|
||||||
|
#endif
|
||||||
|
#else /* !HAS_SNPRINTF */
|
||||||
|
|
||||||
|
#ifdef LIBXT
|
||||||
|
#define snprintf _XtSnprintf
|
||||||
|
#define vsnprintf _XtVsnprintf
|
||||||
|
#endif
|
||||||
|
#ifdef LIBX11
|
||||||
|
#define snprintf _XSnprintf
|
||||||
|
#define vsnprintf _XVsnprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1 /* the system might have no X11 headers. -MM */
|
||||||
|
#include <X11/Xos.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#else /* but we still need this... */
|
||||||
|
#include <sys/types.h>
|
||||||
|
/* adjust the following defines if necessary (pre-ANSI) */
|
||||||
|
#define NeedFunctionPrototypes 1
|
||||||
|
#define NeedVarargsPrototypes 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NeedVarargsPrototypes
|
||||||
|
#define HAVE_STDARG_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STDARG_H
|
||||||
|
#include <stdarg.h>
|
||||||
|
extern int snprintf (char *str, size_t count, const char *fmt, ...);
|
||||||
|
extern int vsnprintf (char *str, size_t count, const char *fmt, va_list arg);
|
||||||
|
#else
|
||||||
|
extern int snprintf ();
|
||||||
|
extern int vsnprintf ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAS_SNPRINTF */
|
||||||
|
|
||||||
|
#endif /* SNPRINTF_H */
|
80
mbsebbs/sub.c
Normal file
80
mbsebbs/sub.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <pwd.h>
|
||||||
|
#include "sub.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define BAD_SUBROOT2 "invalid root `%s' for user `%s'\n"
|
||||||
|
#define NO_SUBROOT2 "no subsystem root `%s' for user `%s'\n"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* subsystem - change to subsystem root
|
||||||
|
*
|
||||||
|
* A subsystem login is indicated by the presense of a "*" as
|
||||||
|
* the first character of the login shell. The given home
|
||||||
|
* directory will be used as the root of a new filesystem which
|
||||||
|
* the user is actually logged into.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void subsystem(const struct passwd *pw)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The new root directory must begin with a "/" character.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pw->pw_dir[0] != '/') {
|
||||||
|
printf("Invalid root directory \"%s\"\n", pw->pw_dir);
|
||||||
|
syslog(LOG_WARNING, BAD_SUBROOT2, pw->pw_dir, pw->pw_name);
|
||||||
|
closelog();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The directory must be accessible and the current process
|
||||||
|
* must be able to change into it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) {
|
||||||
|
printf("Can't change root directory to \"%s\"\n", pw->pw_dir);
|
||||||
|
syslog(LOG_WARNING, NO_SUBROOT2, pw->pw_dir, pw->pw_name);
|
||||||
|
closelog();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
8
mbsebbs/sub.h
Normal file
8
mbsebbs/sub.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _SUB_H
|
||||||
|
#define _SUB_H
|
||||||
|
|
||||||
|
void subsystem(const struct passwd *);
|
||||||
|
|
||||||
|
#endif
|
90
mbsebbs/ttytype.c
Normal file
90
mbsebbs/ttytype.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "env.h"
|
||||||
|
#include "ttytype.h"
|
||||||
|
|
||||||
|
// extern char *getenv();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ttytype - set ttytype from port to terminal type mapping database
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ttytype(const char *line)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
char *typefile;
|
||||||
|
char *cp;
|
||||||
|
char type[BUFSIZ];
|
||||||
|
char port[BUFSIZ];
|
||||||
|
|
||||||
|
if (getenv ("TERM"))
|
||||||
|
return;
|
||||||
|
if ((typefile=getdef_str("TTYTYPE_FILE")) == NULL )
|
||||||
|
return;
|
||||||
|
if (access(typefile, F_OK))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (! (fp = fopen (typefile, "r"))) {
|
||||||
|
perror (typefile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (fgets(buf, sizeof buf, fp)) {
|
||||||
|
if (buf[0] == '#')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((cp = strchr (buf, '\n')))
|
||||||
|
*cp = '\0';
|
||||||
|
|
||||||
|
#if defined(SUN) || defined(BSD) || defined(SUN4)
|
||||||
|
if ((sscanf (buf, "%s \"%*[^\"]\" %s", port, type) == 2 ||
|
||||||
|
sscanf (buf, "%s %*s %s", port, type) == 2) &&
|
||||||
|
strcmp (line, port) == 0)
|
||||||
|
break;
|
||||||
|
#else /* USG */
|
||||||
|
if (sscanf (buf, "%s %s", type, port) == 2 &&
|
||||||
|
strcmp (line, port) == 0)
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (! feof (fp) && ! ferror (fp))
|
||||||
|
addenv("TERM", type);
|
||||||
|
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
8
mbsebbs/ttytype.h
Normal file
8
mbsebbs/ttytype.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _TTYTYPE_H
|
||||||
|
#define _TTYTYPE_H
|
||||||
|
|
||||||
|
void ttytype(const char *);
|
||||||
|
|
||||||
|
#endif
|
67
mbsebbs/tz.c
Normal file
67
mbsebbs/tz.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include "getdef.h"
|
||||||
|
#include "tz.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* tz - return local timezone name
|
||||||
|
*
|
||||||
|
* tz() determines the name of the local timezone by reading the
|
||||||
|
* contents of the file named by ``fname''.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *tz(const char *fname)
|
||||||
|
{
|
||||||
|
FILE *fp = 0;
|
||||||
|
static char tzbuf[BUFSIZ];
|
||||||
|
const char *def_tz;
|
||||||
|
|
||||||
|
if ((fp = fopen(fname,"r")) == NULL ||
|
||||||
|
fgets (tzbuf, sizeof (tzbuf), fp) == NULL) {
|
||||||
|
if (! (def_tz = getdef_str ("ENV_TZ")) || def_tz[0] == '/')
|
||||||
|
def_tz = "TZ=CST6CDT";
|
||||||
|
|
||||||
|
strcpy (tzbuf, def_tz);
|
||||||
|
} else
|
||||||
|
tzbuf[strlen(tzbuf) - 1] = '\0';
|
||||||
|
|
||||||
|
if (fp)
|
||||||
|
(void) fclose(fp);
|
||||||
|
|
||||||
|
return tzbuf;
|
||||||
|
}
|
8
mbsebbs/tz.h
Normal file
8
mbsebbs/tz.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _TZTZ_H
|
||||||
|
#define _TZTZ_H
|
||||||
|
|
||||||
|
char *tz(const char *);
|
||||||
|
|
||||||
|
#endif
|
66
mbsebbs/ulimit.c
Normal file
66
mbsebbs/ulimit.c
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyright ....: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
|
#if HAVE_ULIMIT_H
|
||||||
|
#include <ulimit.h>
|
||||||
|
|
||||||
|
#ifndef UL_SETFSIZE
|
||||||
|
#ifdef UL_SFILLIM
|
||||||
|
#define UL_SETFSIZE UL_SFILLIM
|
||||||
|
#else
|
||||||
|
#define UL_SETFSIZE 2
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#elif HAVE_SYS_RESOURCE_H
|
||||||
|
#include <sys/time.h> /* for struct timeval on sunos4 */
|
||||||
|
/* XXX - is the above ok or should it be <time.h> on ultrix? */
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
#include "ulimit.h"
|
||||||
|
|
||||||
|
|
||||||
|
void set_filesize_limit(int blocks)
|
||||||
|
{
|
||||||
|
#if HAVE_ULIMIT_H
|
||||||
|
ulimit(UL_SETFSIZE, blocks);
|
||||||
|
#elif defined(RLIMIT_FSIZE)
|
||||||
|
struct rlimit rlimit_fsize;
|
||||||
|
|
||||||
|
rlimit_fsize.rlim_cur = rlimit_fsize.rlim_max = 512L * blocks;
|
||||||
|
setrlimit(RLIMIT_FSIZE, &rlimit_fsize);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
9
mbsebbs/ulimit.h
Normal file
9
mbsebbs/ulimit.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _ULIMIT_H_H
|
||||||
|
#define _ULIMIT_H_H
|
||||||
|
|
||||||
|
|
||||||
|
void set_filesize_limit(int);
|
||||||
|
|
||||||
|
#endif
|
477
mbsebbs/utmp.c
Normal file
477
mbsebbs/utmp.c
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
* Purpose ...............: MBSE BBS Shadow Password Suite
|
||||||
|
* Original Source .......: Shadow Password Suite
|
||||||
|
* Original Copyrioght ...: Julianne Frances Haugh and others.
|
||||||
|
*
|
||||||
|
*****************************************************************************
|
||||||
|
* Copyright (C) 1997-2001
|
||||||
|
*
|
||||||
|
* Michiel Broek FIDO: 2:280/2802
|
||||||
|
* Beekmansbos 10
|
||||||
|
* 1971 BV IJmuiden
|
||||||
|
* the Netherlands
|
||||||
|
*
|
||||||
|
* This file is part of MBSE BBS.
|
||||||
|
*
|
||||||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||||||
|
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
#include "mblogin.h"
|
||||||
|
#include <utmp.h>
|
||||||
|
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
#include <utmpx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "utmp.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
extern struct utmpx utxent;
|
||||||
|
#endif
|
||||||
|
extern struct utmp utent;
|
||||||
|
|
||||||
|
// extern struct utmp *getutent();
|
||||||
|
// extern struct utmp *getutline();
|
||||||
|
// extern void setutent();
|
||||||
|
// extern void endutent();
|
||||||
|
// extern time_t time();
|
||||||
|
// extern char *ttyname();
|
||||||
|
// extern long lseek();
|
||||||
|
|
||||||
|
#define NO_UTENT \
|
||||||
|
"No utmp entry. You must exec \"login\" from the lowest level \"sh\""
|
||||||
|
#define NO_TTY \
|
||||||
|
"Unable to determine your tty name."
|
||||||
|
|
||||||
|
/*
|
||||||
|
* checkutmp - see if utmp file is correct for this process
|
||||||
|
*
|
||||||
|
* System V is very picky about the contents of the utmp file
|
||||||
|
* and requires that a slot for the current process exist.
|
||||||
|
* The utmp file is scanned for an entry with the same process
|
||||||
|
* ID. If no entry exists the process exits with a message.
|
||||||
|
*
|
||||||
|
* The "picky" flag is for network and other logins that may
|
||||||
|
* use special flags. It allows the pid checks to be overridden.
|
||||||
|
* This means that getty should never invoke login with any
|
||||||
|
* command line flags.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__linux__) /* XXX */
|
||||||
|
|
||||||
|
void
|
||||||
|
checkutmp(int picky)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
struct utmp *ut;
|
||||||
|
pid_t pid = getpid();
|
||||||
|
|
||||||
|
setutent();
|
||||||
|
|
||||||
|
/* First, try to find a valid utmp entry for this process. */
|
||||||
|
while ((ut = getutent()))
|
||||||
|
if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
|
||||||
|
(ut->ut_type==LOGIN_PROCESS || ut->ut_type==USER_PROCESS))
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* If there is one, just use it, otherwise create a new one. */
|
||||||
|
if (ut) {
|
||||||
|
utent = *ut;
|
||||||
|
} else {
|
||||||
|
if (picky) {
|
||||||
|
puts(NO_UTENT);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
line = ttyname(0);
|
||||||
|
if (!line) {
|
||||||
|
puts(NO_TTY);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (strncmp(line, "/dev/", 5) == 0)
|
||||||
|
line += 5;
|
||||||
|
memset((void *) &utent, 0, sizeof utent);
|
||||||
|
utent.ut_type = LOGIN_PROCESS;
|
||||||
|
utent.ut_pid = pid;
|
||||||
|
strncpy(utent.ut_line, line, sizeof utent.ut_line);
|
||||||
|
/* XXX - assumes /dev/tty?? */
|
||||||
|
strncpy(utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id);
|
||||||
|
strcpy(utent.ut_user, "LOGIN");
|
||||||
|
time(&utent.ut_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(LOGIN_PROCESS)
|
||||||
|
|
||||||
|
void
|
||||||
|
checkutmp(int picky)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
struct utmp *ut;
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
struct utmpx *utx;
|
||||||
|
#endif
|
||||||
|
pid_t pid = getpid();
|
||||||
|
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
setutxent();
|
||||||
|
#endif
|
||||||
|
setutent();
|
||||||
|
|
||||||
|
if (picky) {
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
while ((utx = getutxent()))
|
||||||
|
if (utx->ut_pid == pid)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (utx)
|
||||||
|
utxent = *utx;
|
||||||
|
#endif
|
||||||
|
while ((ut = getutent()))
|
||||||
|
if (ut->ut_pid == pid)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ut)
|
||||||
|
utent = *ut;
|
||||||
|
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
endutxent();
|
||||||
|
#endif
|
||||||
|
endutent();
|
||||||
|
|
||||||
|
if (!ut) {
|
||||||
|
puts(NO_UTENT);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#ifndef UNIXPC
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is no ut_line value in this record, fill
|
||||||
|
* it in by getting the TTY name and stuffing it in
|
||||||
|
* the structure. The UNIX/PC is broken in this regard
|
||||||
|
* and needs help ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (utent.ut_line[0] == '\0')
|
||||||
|
#endif /* !UNIXPC */
|
||||||
|
{
|
||||||
|
if (!(line = ttyname(0))) {
|
||||||
|
puts(NO_TTY);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (strncmp(line, "/dev/", 5) == 0)
|
||||||
|
line += 5;
|
||||||
|
strncpy(utent.ut_line, line, sizeof utent.ut_line);
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
strncpy(utxent.ut_line, line, sizeof utxent.ut_line);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!(line = ttyname(0))) {
|
||||||
|
puts(NO_TTY);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (strncmp(line, "/dev/", 5) == 0)
|
||||||
|
line += 5;
|
||||||
|
|
||||||
|
strncpy (utent.ut_line, line, sizeof utent.ut_line);
|
||||||
|
if ((ut = getutline(&utent)))
|
||||||
|
strncpy(utent.ut_id, ut->ut_id, sizeof ut->ut_id);
|
||||||
|
|
||||||
|
strcpy(utent.ut_user, "LOGIN");
|
||||||
|
utent.ut_pid = getpid();
|
||||||
|
utent.ut_type = LOGIN_PROCESS;
|
||||||
|
time(&utent.ut_time);
|
||||||
|
#if HAVE_UTMPX_H
|
||||||
|
strncpy(utxent.ut_line, line, sizeof utxent.ut_line);
|
||||||
|
if ((utx = getutxline(&utxent)))
|
||||||
|
strncpy(utxent.ut_id, utx->ut_id, sizeof utxent.ut_id);
|
||||||
|
|
||||||
|
strcpy(utxent.ut_user, "LOGIN");
|
||||||
|
utxent.ut_pid = utent.ut_pid;
|
||||||
|
utxent.ut_type = utent.ut_type;
|
||||||
|
gettimeofday((struct timeval *) &utxent.ut_tv, NULL);
|
||||||
|
utent.ut_time = utxent.ut_tv.tv_sec;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !USG */
|
||||||
|
|
||||||
|
void
|
||||||
|
checkutmp(int picky)
|
||||||
|
{
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hand-craft a new utmp entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memzero(&utent, sizeof utent);
|
||||||
|
if (! (line = ttyname (0))) {
|
||||||
|
puts (NO_TTY);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
if (strncmp (line, "/dev/", 5) == 0)
|
||||||
|
line += 5;
|
||||||
|
|
||||||
|
(void) strncpy (utent.ut_line, line, sizeof utent.ut_line);
|
||||||
|
(void) time (&utent.ut_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !USG */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some systems already have updwtmp() and possibly updwtmpx(). Others
|
||||||
|
* don't, so we re-implement these functions if necessary. --marekm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_UPDWTMP
|
||||||
|
void updwtmp(const char *filename, const struct utmp *ut)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(filename, O_APPEND | O_WRONLY, 0);
|
||||||
|
if (fd >= 0) {
|
||||||
|
write(fd, (const char *) ut, sizeof(*ut));
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ! HAVE_UPDWTMP */
|
||||||
|
|
||||||
|
#ifdef HAVE_UTMPX_H
|
||||||
|
#ifndef HAVE_UPDWTMPX
|
||||||
|
static void
|
||||||
|
updwtmpx(const char *filename, const struct utmpx *utx)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(filename, O_APPEND | O_WRONLY, 0);
|
||||||
|
if (fd >= 0) {
|
||||||
|
write(fd, (const char *) utx, sizeof(*utx));
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* ! HAVE_UPDWTMPX */
|
||||||
|
#endif /* ! HAVE_UTMPX_H */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setutmp - put a USER_PROCESS entry in the utmp file
|
||||||
|
*
|
||||||
|
* setutmp changes the type of the current utmp entry to
|
||||||
|
* USER_PROCESS. the wtmp file will be updated as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__linux__) /* XXX */
|
||||||
|
|
||||||
|
void
|
||||||
|
setutmp(const char *name, const char *line, const char *host)
|
||||||
|
{
|
||||||
|
utent.ut_type = USER_PROCESS;
|
||||||
|
strncpy(utent.ut_user, name, sizeof utent.ut_user);
|
||||||
|
time(&utent.ut_time);
|
||||||
|
/* other fields already filled in by checkutmp above */
|
||||||
|
setutent();
|
||||||
|
pututline(&utent);
|
||||||
|
endutent();
|
||||||
|
updwtmp(_WTMP_FILE, &utent);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif HAVE_UTMPX_H
|
||||||
|
|
||||||
|
void
|
||||||
|
setutmp(const char *name, const char *line, const char *host)
|
||||||
|
{
|
||||||
|
struct utmp *utmp, utline;
|
||||||
|
struct utmpx *utmpx, utxline;
|
||||||
|
pid_t pid = getpid ();
|
||||||
|
int found_utmpx = 0, found_utmp = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The canonical device name doesn't include "/dev/"; skip it
|
||||||
|
* if it is already there.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (strncmp (line, "/dev/", 5) == 0)
|
||||||
|
line += 5;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update utmpx. We create an empty entry in case there is
|
||||||
|
* no matching entry in the utmpx file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
setutxent ();
|
||||||
|
setutent ();
|
||||||
|
|
||||||
|
while (utmpx = getutxent ()) {
|
||||||
|
if (utmpx->ut_pid == pid) {
|
||||||
|
found_utmpx = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (utmp = getutent ()) {
|
||||||
|
if (utmp->ut_pid == pid) {
|
||||||
|
found_utmp = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the entry matching `pid' cannot be found, create a new
|
||||||
|
* entry with the device name in it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (! found_utmpx) {
|
||||||
|
memset ((void *) &utxline, 0, sizeof utxline);
|
||||||
|
strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
|
||||||
|
utxline.ut_pid = getpid ();
|
||||||
|
} else {
|
||||||
|
utxline = *utmpx;
|
||||||
|
if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
|
||||||
|
memmove (utxline.ut_line, utxline.ut_line + 5,
|
||||||
|
sizeof utxline.ut_line - 5);
|
||||||
|
utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! found_utmp) {
|
||||||
|
memset ((void *) &utline, 0, sizeof utline);
|
||||||
|
strncpy (utline.ut_line, utxline.ut_line,
|
||||||
|
sizeof utline.ut_line);
|
||||||
|
utline.ut_pid = utxline.ut_pid;
|
||||||
|
} else {
|
||||||
|
utline = *utmp;
|
||||||
|
if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
|
||||||
|
memmove (utline.ut_line, utline.ut_line + 5,
|
||||||
|
sizeof utline.ut_line - 5);
|
||||||
|
utline.ut_line[sizeof utline.ut_line - 5] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in the fields in the utmpx entry and write it out. Do
|
||||||
|
* the utmp entry at the same time to make sure things don't
|
||||||
|
* get messed up.
|
||||||
|
*/
|
||||||
|
|
||||||
|
strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
|
||||||
|
strncpy (utline.ut_user, name, sizeof utline.ut_user);
|
||||||
|
|
||||||
|
utline.ut_type = utxline.ut_type = USER_PROCESS;
|
||||||
|
|
||||||
|
gettimeofday(&utxline.ut_tv, NULL);
|
||||||
|
utline.ut_time = utxline.ut_tv.tv_sec;
|
||||||
|
|
||||||
|
strncpy(utxline.ut_host, host ? host : "", sizeof utxline.ut_host);
|
||||||
|
|
||||||
|
pututxline (&utxline);
|
||||||
|
pututline (&utline);
|
||||||
|
|
||||||
|
updwtmpx(_WTMP_FILE "x", &utxline);
|
||||||
|
updwtmp(_WTMP_FILE, &utline);
|
||||||
|
|
||||||
|
utxent = utxline;
|
||||||
|
utent = utline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !SVR4 */
|
||||||
|
|
||||||
|
void
|
||||||
|
setutmp(const char *name, const char *line)
|
||||||
|
{
|
||||||
|
struct utmp utmp;
|
||||||
|
int fd;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
if ((fd = open(_UTMP_FILE, O_RDWR)) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if !defined(SUN) && !defined(BSD) && !defined(SUN4) /* XXX */
|
||||||
|
while (!found && read(fd, (char *)&utmp, sizeof utmp) == sizeof utmp) {
|
||||||
|
if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line))
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (! found) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a brand-new entry. Clear it out and fill it in
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
memzero(&utmp, sizeof utmp);
|
||||||
|
strncpy(utmp.ut_line, line, (int) sizeof utmp.ut_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill in the parts of the UTMP entry. BSD has just the name,
|
||||||
|
* while System V has the name, PID and a type.
|
||||||
|
*/
|
||||||
|
|
||||||
|
strncpy(utmp.ut_user, name, sizeof utent.ut_user);
|
||||||
|
#ifdef USER_PROCESS
|
||||||
|
utmp.ut_type = USER_PROCESS;
|
||||||
|
utmp.ut_pid = getpid ();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put in the current time (common to everyone)
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void) time (&utmp.ut_time);
|
||||||
|
|
||||||
|
#ifdef UT_HOST
|
||||||
|
/*
|
||||||
|
* Update the host name field for systems with networking support
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void) strncpy (utmp.ut_host, utent.ut_host, (int) sizeof utmp.ut_host);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locate the correct position in the UTMP file for this
|
||||||
|
* entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_TTYSLOT
|
||||||
|
(void) lseek (fd, (off_t) (sizeof utmp) * ttyslot (), SEEK_SET);
|
||||||
|
#else
|
||||||
|
if (found) /* Back up a splot */
|
||||||
|
lseek (fd, (off_t) - sizeof utmp, SEEK_CUR);
|
||||||
|
else /* Otherwise, go to the end of the file */
|
||||||
|
lseek (fd, (off_t) 0, SEEK_END);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scribble out the new entry and close the file. We're done
|
||||||
|
* with UTMP, next we do WTMP (which is real easy, put it on
|
||||||
|
* the end of the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void) write (fd, (char *) &utmp, sizeof utmp);
|
||||||
|
(void) close (fd);
|
||||||
|
|
||||||
|
updwtmp(_WTMP_FILE, &utmp);
|
||||||
|
utent = utmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SVR4 */
|
21
mbsebbs/utmp.h
Normal file
21
mbsebbs/utmp.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#ifndef _UTMP_HH
|
||||||
|
#define _UTMP_HH
|
||||||
|
|
||||||
|
|
||||||
|
void checkutmp(int);
|
||||||
|
|
||||||
|
#ifndef HAVE_UPDWTMP
|
||||||
|
void updwtmp(const char *, const struct utmp *);
|
||||||
|
#endif /* ! HAVE_UPDWTMP */
|
||||||
|
|
||||||
|
#ifdef HAVE_UTMPX_H
|
||||||
|
#ifndef HAVE_UPDWTMPX
|
||||||
|
static void updwtmpx(const char *, const struct utmpx *);
|
||||||
|
#endif /* ! HAVE_UPDWTMPX */
|
||||||
|
#endif /* ! HAVE_UTMPX_H */
|
||||||
|
|
||||||
|
void setutmp(const char *, const char *, const char *);
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user