Initial revision origin/aland
authoraland <aland>
Mon, 16 Aug 1999 17:55:05 +0000 (17:55 +0000)
committeraland <aland>
Mon, 16 Aug 1999 17:55:05 +0000 (17:55 +0000)
151 files changed:
COPYRIGHT [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Make.inc.in [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
README [new file with mode: 0644]
acconfig.h [new file with mode: 0644]
c [new file with mode: 0755]
config.h.bot [new file with mode: 0644]
config.h.top [new file with mode: 0644]
configure.in [new file with mode: 0644]
debian/conffiles [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/postinst [new file with mode: 0644]
debian/postrm [new file with mode: 0755]
debian/prerm [new file with mode: 0644]
debian/rules [new file with mode: 0755]
doc/00-OLD/INSTALL.OLD [new file with mode: 0644]
doc/ChangeLog [new file with mode: 0644]
doc/Makefile.in [new file with mode: 0644]
doc/PAM [new file with mode: 0644]
doc/README [new file with mode: 0644]
doc/README.Y2K [new file with mode: 0644]
doc/Simultaneous-Use [new file with mode: 0644]
doc/builddbm.8rad [new file with mode: 0644]
doc/cache [new file with mode: 0644]
doc/cisco [new file with mode: 0644]
doc/clients.5rad [new file with mode: 0644]
doc/naslist.5rad [new file with mode: 0644]
doc/processing_users_file [new file with mode: 0644]
doc/proxy [new file with mode: 0644]
doc/radiusd.8 [new file with mode: 0644]
doc/radlast.1 [new file with mode: 0644]
doc/radtest.1 [new file with mode: 0644]
doc/raduse.1 [new file with mode: 0644]
doc/radwatch.8 [new file with mode: 0644]
doc/radwho.1 [new file with mode: 0644]
doc/radzap.1 [new file with mode: 0644]
raddb/Makefile.in [new file with mode: 0644]
raddb/clients [new file with mode: 0644]
raddb/dictionary [new file with mode: 0644]
raddb/dictionary.acc [new file with mode: 0644]
raddb/dictionary.ascend [new file with mode: 0644]
raddb/dictionary.cisco [new file with mode: 0644]
raddb/dictionary.compat [new file with mode: 0644]
raddb/dictionary.livingston [new file with mode: 0644]
raddb/dictionary.shiva [new file with mode: 0644]
raddb/dictionary.tunnel [new file with mode: 0644]
raddb/dictionary.usr [new file with mode: 0644]
raddb/dictionary.versanet [new file with mode: 0644]
raddb/hints [new file with mode: 0644]
raddb/huntgroups [new file with mode: 0644]
raddb/modules [new file with mode: 0644]
raddb/naslist [new file with mode: 0644]
raddb/naspasswd [new file with mode: 0644]
raddb/realms [new file with mode: 0644]
raddb/users [new file with mode: 0644]
redhat/radiusd-cistron-1.5.4.3.spec [new file with mode: 0644]
redhat/radiusd-logrotate [new file with mode: 0644]
redhat/radiusd-pam [new file with mode: 0644]
redhat/rc.radiusd-redhat [new file with mode: 0755]
scripts/Makefile.in [new file with mode: 0644]
scripts/radiusd.cron.daily [new file with mode: 0755]
scripts/radiusd.cron.monthly [new file with mode: 0755]
scripts/radwatch.in [new file with mode: 0755]
scripts/rc.radiusd.in [new file with mode: 0755]
share/dictionary [new file with mode: 0644]
share/dictionary.acc [new file with mode: 0644]
share/dictionary.ascend [new file with mode: 0644]
share/dictionary.cisco [new file with mode: 0644]
share/dictionary.compat [new file with mode: 0644]
share/dictionary.livingston [new file with mode: 0644]
share/dictionary.shiva [new file with mode: 0644]
share/dictionary.tunnel [new file with mode: 0644]
share/dictionary.usr [new file with mode: 0644]
share/dictionary.versanet [new file with mode: 0644]
src/Makefile.in [new file with mode: 0644]
src/include/autoconf.h.in [new file with mode: 0644]
src/include/conf.h [new file with mode: 0644]
src/include/libradius.h [new file with mode: 0644]
src/include/md5.h [new file with mode: 0644]
src/include/modules.h [new file with mode: 0644]
src/include/radius.h [new file with mode: 0644]
src/include/radiusd.h [new file with mode: 0644]
src/include/radutmp.h [new file with mode: 0644]
src/include/sysutmp.h [new file with mode: 0644]
src/include/token.h [new file with mode: 0644]
src/lib/Makefile.in [new file with mode: 0644]
src/lib/dict.c [new file with mode: 0644]
src/lib/log.c [new file with mode: 0644]
src/lib/md5.c [new file with mode: 0644]
src/lib/misc.c [new file with mode: 0644]
src/lib/print.c [new file with mode: 0644]
src/lib/radius.c [new file with mode: 0644]
src/lib/token.c [new file with mode: 0644]
src/lib/valuepair.c [new file with mode: 0644]
src/main/00-OLD/Make.inc [new file with mode: 0644]
src/main/00-OLD/Makefile [new file with mode: 0644]
src/main/00-OLD/Makefile.BSD [new file with mode: 0644]
src/main/00-OLD/Makefile.lnx [new file with mode: 0644]
src/main/00-OLD/Makefile.osf [new file with mode: 0644]
src/main/00-OLD/Makefile.sunos5 [new file with mode: 0644]
src/main/Makefile.in [new file with mode: 0644]
src/main/acct.c [new file with mode: 0644]
src/main/auth.c [new file with mode: 0644]
src/main/builddbm.c [new file with mode: 0644]
src/main/checkrad.pl.in [new file with mode: 0644]
src/main/exec.c [new file with mode: 0644]
src/main/files.c [new file with mode: 0644]
src/main/log.c [new file with mode: 0644]
src/main/makelist.sh [new file with mode: 0755]
src/main/modules.c [new file with mode: 0644]
src/main/modules.sh [new file with mode: 0755]
src/main/modules_static.h.in [new file with mode: 0644]
src/main/nas.c [new file with mode: 0644]
src/main/proxy.c [new file with mode: 0644]
src/main/radclient.c [new file with mode: 0644]
src/main/radiusd.c [new file with mode: 0644]
src/main/radlast.in [new file with mode: 0755]
src/main/radtest.in [new file with mode: 0644]
src/main/raduse.c [new file with mode: 0644]
src/main/radutmp.c [new file with mode: 0644]
src/main/radwho.c [new file with mode: 0644]
src/main/radzap.c [new file with mode: 0644]
src/main/timestr.c [new file with mode: 0644]
src/main/util.c [new file with mode: 0644]
src/main/valuepair.c [new file with mode: 0644]
src/main/version.c [new file with mode: 0644]
src/modules/Makefile.in [new file with mode: 0644]
src/modules/README.modules [new file with mode: 0644]
src/modules/checkconfig [new file with mode: 0755]
src/modules/rlm_example/Makefile [new file with mode: 0644]
src/modules/rlm_example/rlm_example.c [new file with mode: 0644]
src/modules/rlm_files/Makefile [new file with mode: 0644]
src/modules/rlm_files/rlm_files.c [new file with mode: 0644]
src/modules/rlm_pam/Makefile [new file with mode: 0644]
src/modules/rlm_pam/rlm_pam.c [new file with mode: 0644]
src/modules/rlm_preprocess/Makefile [new file with mode: 0644]
src/modules/rlm_preprocess/rlm_preprocess.c [new file with mode: 0644]
src/modules/rlm_unix/Makefile [new file with mode: 0644]
src/modules/rlm_unix/cache.c [new file with mode: 0644]
src/modules/rlm_unix/cache.h [new file with mode: 0644]
src/modules/rlm_unix/config.h [new file with mode: 0644]
src/modules/rlm_unix/config.mak [new file with mode: 0644]
src/modules/rlm_unix/rlm_unix.c [new file with mode: 0644]
src/modules/rules.mak [new file with mode: 0644]
todo/TODO [new file with mode: 0644]
todo/proposed-new-users [new file with mode: 0644]
todo/radius.conf.sample2 [new file with mode: 0644]
todo/realm.c [new file with mode: 0644]
todo/realm.h [new file with mode: 0644]
todo/realms [new file with mode: 0644]

diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644 (file)
index 0000000..03f98dc
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,22 @@
+
+       Most code in this package was written by Miquel van Smoorenburg
+       <miquels@cistron.nl> for Cistron Internet Services B.V.
+
+       Copyright (C) 1997-1999 Cistron Internet Services B.V.
+
+       The license for all source code and documentation except
+       the files in /lib is the GNU GPL version 2:
+
+       This program 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 of the License, or (at your option) any later version.
+
+       The license for all files in the /lib directory is the
+       GNU LGPL version 2:
+
+       This library is free software; you can redistribute it and/or
+       modify it under the terms of the GNU Library General Public
+       License as published by the Free Software Foundation; either
+       version 2 of the License, or (at your option) any later version.
+
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..c63abe7
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,4 @@
+
+Please read the README in the doc/ subdirectory. Paragraph 2 tells
+you how to configure, compile and install Cistron Radius.
+
diff --git a/Make.inc.in b/Make.inc.in
new file mode 100644 (file)
index 0000000..3b185c1
--- /dev/null
@@ -0,0 +1,40 @@
+#
+# Make.inc.in  Common Makefile stuff for the cistron-radius package.
+#
+# Version:     @(#)Makefile.inc.in  1.00 01-Jul-1999  miquels@cistron.nl
+#
+
+# Location of files.
+prefix         = @prefix@
+exec_prefix    = @exec_prefix@
+sysconfdir     = @sysconfdir@
+localstatedir  = @localstatedir@
+libdir         = @libdir@
+bindir         = @bindir@
+sbindir                = @sbindir@
+mandir         = @mandir@
+logdir         = @logdir@
+raddbdir       = @raddbdir@
+radacctdir     = @radacctdir@
+
+CC             = @CC@
+RANLIB         = @RANLIB@
+INCLUDE                = 
+CFLAGS         = $(INCLUDE) @CFLAGS@
+LDFLAGS                = @LDFLAGS@
+
+LCRYPT         = @CRYPTLIB@
+LDBM           = @DBMLIB@
+LIBDL          = @LIBDL@
+SOCKETLIB      = @SOCKETLIB@
+NSLLIB         = @NSLLIB@
+
+LOGDIR         = @logdir@
+RADDBDIR       = @raddbdir@
+RUNDIR         = @localstatedir@/run
+SBINDIR                = @sbindir@
+RADIR          = @radacctdir@
+
+MODULES                = @MODULES@
+MODULE_PATHS   = @MODULE_PATHS@
+
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..09302a2
--- /dev/null
@@ -0,0 +1,53 @@
+#
+# Makefile     Makefile for the cistron-radius package.
+#
+# Version:     @(#)Makefile  1.00 01-Jul-1999  miquels@cistron.nl
+#
+
+@INCLUDE@ @IQUOTE@Make.inc@IQUOTE@
+
+SUBDIRS                = src raddb doc scripts
+WHAT_TO_MAKE   = all
+
+all:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+clean:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+       @rm -f *~ stamp*
+
+install:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+common:
+       @for dir in $(SUBDIRS); do \
+               echo "Making $(WHAT_TO_MAKE) in $$dir..."; \
+               (cd $$dir ; $(MAKE) $(MFLAGS) $(WHAT_TO_MAKE)) || exit 1;\
+       done
+
+distclean: clean
+       rm -f config.cache config.log config.status
+       -find . ! -name configure.in -name \*.in -print | \
+               sed 's/\.in$$//' | \
+               while read file; do rm -f $$file; done
+
+######################################################################
+#
+#  Automatic remaking rules suggested by info:autoconf#Automatic_Remaking
+#
+######################################################################
+configure: configure.in
+       autoconf
+
+# autoheader might not change config.h.in, so touch a stamp file
+config.h.in: stamp-h.in
+stamp-h.in: configure.in acconfig.h config.h.top config.h.bot
+       autoheader
+       echo timestamp > stamp-h.in
+
+config.h: stamp-h
+stamp-h: config.h.in config.status
+       ./config.status
+
+config.status: configure
+       ./config.status --recheck
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..032f4b0
--- /dev/null
+++ b/README
@@ -0,0 +1,10 @@
+
+  debian/      Files to build a radiusd-cistron Debian package
+  doc/         Various snippets of documentation
+  raddb/       Sample files for /etc/raddb
+  scripts/     Sample scripts for startup and maintenance
+  src/         Source code
+  todo/                TODO list and assorted files.
+
+Please see the README and other documentation in the doc/ subdirectory
+
diff --git a/acconfig.h b/acconfig.h
new file mode 100644 (file)
index 0000000..b70569f
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+
+acconfig.h - template used by autoheader to create config.h.in
+config.h.in - used by autoconf to create config.h
+config.h - created by autoconf; contains defines generated by autoconf
+
+*/
+
+@TOP@
+
+/* Do we have shadow support? */
+#undef HAVE_GETSPNAM
+
+/* Do we have socklen_t? */
+#undef HAVE_SOCKLEN_T
+
+/* Do we have libdl support? */
+#undef HAVE_LIBDL
+
+/* Do we want to compile in DBM support? */
+#undef WITH_DBM
+
+/* Do we want to compile in NDBM support? */
+#undef WITH_NDBM
+
+/* Include Ascend hacks */
+#undef WITH_ASCEND_HACK
+
+/* Set Ascend Channels Per Line to N */
+#undef ASCEND_CHANNELS_PER_LINE
+
+/* Include NT Domain hack */
+#undef WITH_NTDOMAIN_HACK
+
+/* Include Specialix Jetstream hacks */
+#undef WITH_SPECIALIX_JETSTREAM_HACK
+
+/* Make dictionary case-independant */
+#undef WITH_DICT_NOCASE
+
+/* Make dictionary case-independant */
+#undef WITH_DICT_NOCASE
diff --git a/c b/c
new file mode 100755 (executable)
index 0000000..08c3509
--- /dev/null
+++ b/c
@@ -0,0 +1,15 @@
+#! /bin/sh
+#
+# c            Short script fragment that configures the paths
+#              exactly as they were in the 1.5.x series of the
+#              Cistron Radius Server.
+#
+# Usage:       ./c
+#
+# Version:     @(#)./c  1.00  25-Jul-1999  miquels@cistron.nl
+#
+
+./configure    --localstatedir=/var \
+               --sysconfdir=/etc "$@" \
+               --without-dynamic-modules
+
diff --git a/config.h.bot b/config.h.bot
new file mode 100644 (file)
index 0000000..0752384
--- /dev/null
@@ -0,0 +1 @@
+/* bar */
diff --git a/config.h.top b/config.h.top
new file mode 100644 (file)
index 0000000..5e72e87
--- /dev/null
@@ -0,0 +1 @@
+/* foo */
diff --git a/configure.in b/configure.in
new file mode 100644 (file)
index 0000000..0dc18e8
--- /dev/null
@@ -0,0 +1,285 @@
+AC_INIT(src/main/radiusd.c)
+AC_CONFIG_HEADER(src/include/autoconf.h)
+AC_REVISION($Revision$)dnl
+dnl AC_PREFIX_DEFAULT(/usr/local)
+
+dnl Check for GNU cc
+AC_PROG_CC
+AC_PROG_RANLIB
+
+dnl Set Default CFLAGS
+if test "$GCC" = "yes"; then
+    CFLAGS="$CFLAGS -Wall -D_GNU_SOURCE"
+fi
+
+dnl extra argument: --with-logdir
+logdir='${localstatedir}/log'
+AC_MSG_CHECKING(logdir)
+AC_ARG_WITH(logdir,
+[  --with-logdir=DIR       Directory for logfiles [LOCALSTATEDIR/log] ],
+[ case "$withval" in
+    no)
+       AC_MSG_ERROR(Need logdir)
+       ;;
+    yes)
+       ;;
+    *)
+       logdir="$withval"
+       ;;
+  esac ]
+)
+AC_SUBST(logdir)
+AC_MSG_RESULT($logdir)
+
+dnl extra argument: --with-radacctdir
+radacctdir='${logdir}/radacct'
+AC_MSG_CHECKING(radacctdir)
+AC_ARG_WITH(radacctdir,
+[  --with-radacctdir=PATH  Directory for detail files [LOGDIR/radacct] ],
+[ case "$withval" in
+    no)
+       AC_MSG_ERROR(Need radacctdir)
+       ;;
+    yes)
+       ;;
+    *)
+       radacctdir="$withval"
+       ;;
+  esac ]
+)
+AC_SUBST(radacctdir)
+AC_MSG_RESULT($radacctdir)
+
+dnl extra argument: --with-raddbdir
+raddbdir='${sysconfdir}/raddb'
+AC_MSG_CHECKING(raddbdir)
+AC_ARG_WITH(raddbdir,
+[  --with-raddbdir=DIR     Directory for config files [SYSCONFDIR/raddb] ],
+[ case "$withval" in
+    no)
+       AC_MSG_ERROR(Need raddbdir)
+       ;;
+    yes)
+       ;;
+    *)
+       raddbdir="$withval"
+       ;;
+  esac ]
+)
+AC_SUBST(raddbdir)
+AC_MSG_RESULT($raddbdir)
+
+dnl extra argument: --with-dbm
+DBMLIB=
+BUILDDBM=
+AC_ARG_WITH(dbm,
+[  --with-dbm              Compile in DBM support],
+[ case "$withval" in
+    no)
+       ;;
+    yes)
+       AC_DEFINE(WITH_DBM)
+       DBMLIB=-ldbm
+       BUILDDBM=builddbm
+  esac ]
+)
+
+dnl extra argument: --with-ndbm
+AC_ARG_WITH(ndbm,
+[  --with-ndbm             Compile in NDBM support],
+[ case "$withval" in
+    no)
+       ;;
+    yes)
+       AC_DEFINE(WITH_NDBM)
+       DBMLIB=-ldb
+       BUILDDBM=builddbm
+  esac ]
+)
+
+AC_SUBST(DBMLIB)
+AC_SUBST(BUILDDBM)
+
+dnl extra argument: --with-ascend-hack
+AC_ARG_WITH(ascend-hack,
+[  --with-ascend-hack      Include Ascend hacks],
+[ case "$withval" in
+    no)
+       ;;
+    yes)
+       AC_DEFINE(WITH_ASCEND_HACK)
+  esac ]
+)
+
+dnl extra argument: --with-ascend-cpl=N
+AC_ARG_WITH(ascend-cpl,
+[  --with-ascend-cpl=N     Set Ascend Channels Per Line to N [23] ],
+[ case "$withval" in
+    *)
+       AC_DEFINE_UNQUOTED(ASCEND_CHANNELS_PER_LINE, $withval)
+  esac ]
+)
+
+dnl extra argument: --with-ntdomain-hack
+AC_ARG_WITH(ntdomain-hack,
+[  --with-ntdomain-hack    Include NT Domain hack],
+[ case "$withval" in
+    no)
+       ;;
+    yes)
+       AC_DEFINE(WITH_NTDOMAIN_HACK)
+  esac ]
+)
+
+dnl extra argument: --with-spcj-hack
+AC_ARG_WITH(spcj-hack,
+[  --with-spcj-hack        Include Specialix Jetstream hacks],
+[ case "$withval" in
+    no)
+       ;;
+    yes)
+       AC_DEFINE(WITH_SPECIALIX_JETSTREAM_HACK)
+  esac ]
+)
+
+dnl extra argument: --with-dict-nocase
+AC_ARG_WITH(dict-nocase,
+[  --with-dict-nocase      Make dictionary case-independant],
+[ case "$withval" in
+    no)
+       ;;
+    yes)
+       AC_DEFINE(WITH_DICT_NOCASE)
+  esac ]
+)
+
+dnl extra argument: --with-dynamic_modules
+WITH_DYNAMIC_MODULES=yes
+AC_ARG_WITH(dynamic-modules,
+[  --with-dynamic-modules  Use runtime loadable modules ],
+[ case "$withval" in
+    *)
+       WITH_DYNAMIC_MODULES=$withval
+  esac ]
+)
+
+dnl See what include-style is used by the make program.
+AC_MSG_CHECKING(include style for make)
+echo "include /dev/null" > testmake.$$
+echo "all:" >> testmake.$$
+make -f testmake.$$ >/dev/null 2>&1
+if test $? = 0
+then
+       INCLUDE=include
+       IQUOTE=
+else
+       INCLUDE=.include
+       IQUOTE='"'
+fi
+rm -f testmake.$$
+AC_MSG_RESULT(" $INCLUDE")
+AC_SUBST(INCLUDE)
+AC_SUBST(IQUOTE)
+
+dnl Check if we have a dynamic linker.
+AC_MSG_CHECKING(for runtime dynamic linker)
+if test "$WITH_DYNAMIC_MODULES" = "yes" && test -f /usr/include/dlfcn.h
+then
+       AC_DEFINE(HAVE_LIBDL)
+       HAVE_LIBDL=1
+       LIBDL="-ldl"
+       AC_MSG_RESULT("found")
+else
+       AC_MSG_RESULT("not found")
+fi
+AC_SUBST(LIBDL)
+
+dnl Modules to be built.
+for i in `( cd src/modules; ls -1d rlm_* )`
+do
+       if test "$HAVE_LIBDL" = ""; then
+               MODULES="$MODULES$i.a "
+               MODULE_PATHS="$MODULE_PATHS../modules/$i/$i.a "
+       else
+               MODULES="$MODULES$i.so "
+       fi
+done
+AC_SUBST(MODULES)
+AC_SUBST(MODULE_PATHS)
+
+dnl Check for programs
+AC_PATH_PROG(PERL, perl, /usr/local/bin/perl)
+if test ! -x $ac_cv_path_PERL; then
+  AC_MSG_ERROR(perl not found - fatal)
+fi
+AC_PATH_PROG(SNMPGET, snmpget, /usr/local/bin/snmpget)
+AC_PATH_PROG(RUSERS, rusers, /usr/bin/rusers)
+
+dnl Check for headers
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+
+AC_CHECK_HEADERS( \
+       crypt.h \
+       errno.h \
+       resource.h \
+       getopt.h \
+       malloc.h \
+       sys/select.h \
+)
+
+AC_CHECK_FUNCS( \
+       getopt_long \
+       lockf \
+       strsignal \
+       snprintf \
+       vsnprintf \
+       setsid \
+)
+
+dnl Check for socklen_t
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/socket.h>],
+  [socklen_t foo],
+  AC_DEFINE(HAVE_SOCKLEN_T),
+)
+
+dnl Check for libcrypt
+dnl We use crypt(3) which may be in libc, or in libcrypt (eg FreeBSD)
+AC_CHECK_LIB(crypt, crypt,
+  CRYPTLIB="-lcrypt",
+)
+AC_SUBST(CRYPTLIB)
+
+dnl Check for -lsocket
+AC_CHECK_LIB(socket, getsockname,
+  SOCKETLIB="-lsocket"
+)
+AC_SUBST(SOCKETLIB)
+
+dnl Check for -lnsl. We don't need yp_all, but usually if we want to
+dnl link against -lsocket we need to include -lnsl as well.
+AC_CHECK_LIB(nsl, yp_all,
+  NSLLIB="-lnsl",
+)
+AC_SUBST(NSLLIB)
+
+AC_OUTPUT(\
+       
+       ./Make.inc \
+       ./Makefile
+       ./src/Makefile \
+       ./src/lib/Makefile \
+       ./src/main/Makefile \
+       ./src/main/checkrad.pl \
+       ./src/main/radlast \
+       ./src/main/radtest \
+       ./src/modules/Makefile \
+       ./raddb/Makefile \
+       ./doc/Makefile \
+       ./scripts/Makefile \
+       ./scripts/rc.radiusd \
+       ./scripts/radwatch \
+)
+
+AC_OUTPUT_COMMANDS([echo timestamp > stamp-h])
diff --git a/debian/conffiles b/debian/conffiles
new file mode 100644 (file)
index 0000000..bbdadd8
--- /dev/null
@@ -0,0 +1,20 @@
+/etc/raddb/clients
+/etc/raddb/dictionary
+/etc/raddb/dictionary.acc
+/etc/raddb/dictionary.ascend
+/etc/raddb/dictionary.cisco
+/etc/raddb/dictionary.compat
+/etc/raddb/dictionary.livingston
+/etc/raddb/dictionary.shiva
+/etc/raddb/dictionary.tunnel
+/etc/raddb/dictionary.usr
+/etc/raddb/dictionary.versanet
+/etc/raddb/hints
+/etc/raddb/huntgroups
+/etc/raddb/naslist
+/etc/raddb/naspasswd
+/etc/raddb/users
+/etc/raddb/realms
+/etc/init.d/radiusd
+/etc/cron.daily/radiusd
+/etc/cron.monthly/radiusd
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..35728aa
--- /dev/null
@@ -0,0 +1,16 @@
+Source: radiusd-cistron
+Section: net
+Priority: standard
+Maintainer: Miquel van Smoorenburg <miquels@cistron.nl>
+Standards-Version: 2.4.0.0
+
+Package: radiusd-cistron
+Architecture: any
+Depends: ${shlibs:Depends}
+Provides: radiusd
+Conflicts: radiusd, radiusd-livingston
+Description: Cistron version of Radius.
+ This Radius server is based on the Livingston-1.16 server, but is largely
+ compatible with the Livingston-2.01 server. Over radius-2.01, it has
+ support for Exec-Program on authentication, it is possible to limit
+ the number of concurrent logins reliably, and more.
diff --git a/debian/postinst b/debian/postinst
new file mode 100644 (file)
index 0000000..042eead
--- /dev/null
@@ -0,0 +1,28 @@
+#! /bin/sh
+
+case "$1" in
+  configure)
+       update-rc.d radiusd defaults 50 > /dev/null
+       if [ ! -f /var/log/radius.log ]
+       then
+               touch /var/log/radius.log
+               chmod 640 /var/log/radius.log
+               chown root:adm /var/log/radius.log
+       fi
+       if [ ! -f /var/log/radwtmp ]
+       then
+               touch /var/log/radwtmp
+               chmod 644 /var/log/radwtmp
+               chown root:adm /var/log/radius.log
+       fi
+       /etc/init.d/radiusd start
+       ;;
+  abort-upgrade)
+       ;;
+  abort-remove)
+       ;;
+  abort-deconfigure)
+       ;;
+esac
+
+exit 0
diff --git a/debian/postrm b/debian/postrm
new file mode 100755 (executable)
index 0000000..b7f9e09
--- /dev/null
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+case "$1" in
+       remove)
+               update-rc.d radiusd remove > /dev/null
+               ;;
+       purge)
+               rmdir /etc/raddb 2>/dev/null
+               cd /var/log
+               rm -f radius.log radius.log.0 radius.log.*.gz
+               rm -f radwtmp radwtmp.0 radwtmp.*.gz
+               rm -f radutmp radwatch.log
+               [ -d radacct ] && rm -rf radacct
+               ;;
+       *)
+               ;;
+esac
+
+exit 0
diff --git a/debian/prerm b/debian/prerm
new file mode 100644 (file)
index 0000000..c8828e6
--- /dev/null
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+case "$1" in
+  remove)
+       /etc/init.d/radiusd stop
+       ;;
+  upgrade)
+       /etc/init.d/radiusd stop
+       ;;
+  failed-upgrade)
+       ;;
+  deconfigure)
+       ;;
+esac
+
+exit 0
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..4440f5f
--- /dev/null
@@ -0,0 +1,97 @@
+#! /usr/bin/make -f
+#
+#      debian/rules file for radiusd-cistron
+#
+
+SHELL=/bin/bash
+
+# Name.
+package = radiusd-cistron
+tmp     = $(shell pwd)/debian/tmp
+
+define checkdir
+       test -f src/radiusd.c
+endef
+
+build:
+# Builds the binary package.
+       $(checkdir)
+       ( cd src && make )
+       touch build
+
+# Architecture independant files.
+binary-indep:   build
+       $(checkdir)
+
+# Make a binary package (.deb file)
+binary-arch:   build checkroot
+       -rm -rf $(tmp)
+       install -d -g root -m 755 -o root $(tmp)
+       install -d -g root -m 755 -o root $(tmp)/{DEBIAN,usr,etc}
+       install -d -g root -m 755 -o root $(tmp)/etc/init.d
+       install -d -g root -m 755 -o root $(tmp)/etc/raddb
+       install -d -g root -m 755 -o root $(tmp)/usr/{doc,bin,sbin,man}
+       install -d -g root -m 755 -o root $(tmp)/usr/man/{man1,man5,man8}
+       install -d -g root -m 755 -o root $(tmp)/usr/doc/$(package)
+       install -d -g root -m 755 -o root $(tmp)/etc/cron.daily
+       install -d -g root -m 755 -o root $(tmp)/etc/cron.monthly
+       #
+       install -g root -s -m 755 src/radiusd $(tmp)/usr/sbin/radiusd
+       install -g root -s -m 755 src/radzap $(tmp)/usr/bin
+       install -g root -s -m 755 src/radwho $(tmp)/usr/bin
+       install -g root -s -m 755 src/raduse $(tmp)/usr/bin
+       install -g root -m 755 src/radlast $(tmp)/usr/bin
+       install -g root -s -m 755 src/radtest $(tmp)/usr/bin
+       install -g root -m 755 scripts/radwatch $(tmp)/usr/sbin
+       install -g root -m 755 src/checkrad.pl $(tmp)/usr/sbin/checkrad
+       install -g root -m 755 scripts/rc.radiusd $(tmp)/etc/init.d/radiusd
+       install -g root -m 755 scripts/radiusd.cron.daily \
+               $(tmp)/etc/cron.daily/radiusd
+       install -g root -m 755 scripts/radiusd.cron.monthly \
+               $(tmp)/etc/cron.monthly/radiusd
+       perl -pi -e 's#/usr/local/sbin#/usr/sbin#' \
+               $(tmp)/usr/sbin/radwatch $(tmp)/etc/init.d/radiusd
+       #
+       install -g root -m 644 raddb/* $(tmp)/etc/raddb
+       chmod 640 $(tmp)/etc/raddb/users
+       chmod 640 $(tmp)/etc/raddb/clients
+       #
+       install -g root -m 644 doc/*.1 $(tmp)/usr/man/man1
+       install -g root -m 644 doc/*.5rad $(tmp)/usr/man/man5
+       install -g root -m 644 doc/radiusd.8 $(tmp)/usr/man/man8
+       install -g root -m 644 doc/radwatch.8 $(tmp)/usr/man/man8
+       ##install -g root -m 644 doc/builddbm.8rad $(tmp)/usr/man/man8
+       gzip -9f $(tmp)/usr/man/man?/*
+       #
+       install -g root -m 644 debian/changelog \
+               $(tmp)/usr/doc/$(package)/changelog
+       install -g root -m 644 doc/README* \
+               $(tmp)/usr/doc/$(package)
+       gzip -9f $(tmp)/usr/doc/$(package)/*
+       cat COPYRIGHT.* > $(tmp)/usr/doc/$(package)/copyright
+       chown root:root $(tmp)/usr/doc/$(package)/copyright
+       chmod 644 $(tmp)/usr/doc/$(package)/copyright
+       #
+       install -g root -m 755 debian/postinst $(tmp)/DEBIAN
+       install -g root -m 755 debian/prerm $(tmp)/DEBIAN
+       install -g root -m 755 debian/postrm $(tmp)/DEBIAN
+       install -g root -m 644 debian/conffiles $(tmp)/DEBIAN
+       #
+       dpkg-shlibdeps src/radiusd
+       dpkg-gencontrol
+       dpkg --build $(tmp) ..
+       rm -rf $(tmp)
+
+clean: checkroot
+       ( cd src && make clean )
+       rm -f build debian/{files,substvars}
+       rm -rf $(tmp)
+       find . -name '*.bak' -o -name '*~' | xargs -r rm -f --
+
+binary: binary-indep binary-arch
+
+checkroot:
+       $(checkdir)
+       test root = "`whoami`"
+
+.PHONY: binary binary-arch binary-indep clean checkroot
diff --git a/doc/00-OLD/INSTALL.OLD b/doc/00-OLD/INSTALL.OLD
new file mode 100644 (file)
index 0000000..b64cec3
--- /dev/null
@@ -0,0 +1,100 @@
+
+
+                       How to install RADIUS
+
+Last modified 95/01/06
+
+(Also see the RADIUS Chapter in the manual.)
+
+The below examples assume you're installing RADIUS in /etc/raddb but
+you can place it anywhere if you change radius.h and recompile or use
+the -d flag to tell it what directory to find its configuration files in.
+
+If you have pminstall and aren't running NIS (Yellow Pages), run
+pminstall and choose "Install RADIUS", then as root do
+"chmod 700 /etc/raddb", then skip down to SETTING UP CLIENTS.
+
+If you don't have pminstall, do the following:
+
+Add the following 2 lines to /etc/services on your RADIUS server, or
+if you're running NIS (Yellow Pages) add these lines to your services
+NIS map on your NIS master and push the maps.
+
+radius          1645/udp        radiusd
+radacct                1646/udp
+
+Now execute the following commands as root:
+
+umask 22
+mkdir /etc/raddb /usr/adm/radacct
+chmod 700 /etc/raddb /usr/adm/radacct
+
+Copy the contents of /usr/portmaster/radius/raddb into /etc/raddb.
+Compile radiusd from /usr/portmaster/radius/src and place it in
+/etc/radiusd or wherever you prefer.
+
+
+SETTING UP CLIENTS
+
+
+The PortMaster's hostname and the shared secret are placed in
+/etc/raddb/clients, separated by a tab.  Your user entries are placed
+in /etc/raddb/users.  Examples of each can be found in clients.example
+and users.example.  You shouldn't need to change the dictionary file.
+
+Start radiusd (you'll probably want to add this to /etc/rc.local or
+some other file that gets run at system boot time).
+
+/etc/radiusd
+
+radiusd -x will produce debugging output which may be helpful if things
+don't seem to be working.
+
+If radiusd has problems it'll print to /etc/raddb/logfile or /dev/console
+if it can. 
+
+Note that Framed-Compression defaults to on if you don't specify it,
+so SLIP users who don't want VJ header compression MUST include
+Framed-Compression = None.
+
+Configure your PortMaster so that it knows which host the radiusd is
+running on and what the shared secret is.  On the PortMaster, set the
+RADIUS server and the shared secret using the "set authentic" and "set
+secret" commands, or from the Edit RADIUS menu on pmconsole.  The
+secret is case-sensitive and can be up to 16 characters long.  Do not
+use control characters in the secret.  You can configure a backup
+RADIUS server with "set alternate" but it's not required.  Make sure
+all ports have passthrough disabled with "set all security on" followed
+by "reset all" (Warning!  "reset all" will drop off anyone who's on the
+port at the moment.) On older versions of ComOS you'll need to do "set
+s0 security on", "set s1 security on", etc.  Do a "save all" to save
+the changes to nonvolatile memory.
+
+The PortMaster will check its local User Table first, and if it doesn't
+find the user there AND passthrough is disabled AND a RADIUS server is
+set, it will then query the RADIUS server.
+
+Make sure your DNS has an in-addr.arpa entry for the PortMaster if you're 
+using Rlogin to Linux. 
+
+If you're using Rlogin or PortMaster service and get prompted for the
+password twice, you can add the PortMaster's hostname to your
+/etc/hosts.equiv file to get rid of the second password prompt.  
+Do NOT do this if you're using Passthrough and not RADIUS!!!
+
+If you're already in production with the User Table, a good way to
+switch over to using RADIUS is first to add a user to RADIUS that's not
+in the PortMaster's User Table, test with that, and when everything
+checks out use pmreadpass (if on a supported platform) to copy everyone
+from the PortMaster to the /etc/raddb/users file, then get rid of the
+users in the PortMaster's local User Table.  Edit the output from
+pmreadpass to remove the ", Client-ID = 192.9.200.1" clause (the IP
+address will match your PortMaster's IP address).  pmreadpass is
+included in release 3.1 of the PortMaster administration software.
+You'll also need to modify Framed-Filter-Id if you have any.  
+        Framed-Filter-Id = "std.ppp" 
+means that the input filter is std.ppp.in (if it exists) and the output 
+filter is std.ppp.out (if it exists). 
diff --git a/doc/ChangeLog b/doc/ChangeLog
new file mode 100644 (file)
index 0000000..eb6babf
--- /dev/null
@@ -0,0 +1,370 @@
+radiusd-cistron (1.6-alpha3) experimental; urgency=low
+
+  * Changed directory structure. Each module is now in it's own directory.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Thu, 12 Aug 1999 19:12:47 +0200
+
+radiusd-cistron (1.6-alpha2) experimental; urgency=low
+
+  * 1.6-alpha2 "Total Eclipse" release ;)
+  * Moved a lot of code around
+  * Added module code from Alan DeKok
+  * Moved more code around, made some stuff into huntgroups
+  * You can now register a function that is called when a
+    certain valuepair is compared with another
+  * Operator support not completely merged (still todo)
+  * Only tested with a few requests, but hey, it compiles ...
+  * Might rename result constants in modules.h to AUTH_, AUTZ_, ACCT_
+  * Rewrote builddbm.c - last remnant of Livingston code is now gone
+  * Bugs from alpha1 not fixed yet either
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Wed, 11 Aug 1999 00:55:17 +0200
+
+radiusd-cistron (1.6-alpha1) experimental; urgency=low
+
+  * Fix off_t cast in lseek() in radzap.c
+  * Fix getopt() args
+  * Fix some proxy memory leaks - Jonathan Ruano <kobalt@james.encomix.es>
+  * checkrad.pl update by Antonio Dias, rewritten Cyclades PathRAS subroutine
+    and a new Patton 2800 NAS SNMP routine. Also some doc updates.
+  * Fix huntgroup-compare to use operators
+  * Added /etc/shells checking, turned off by default./RADIUSD/ANY/SHELL
+    does the same as /SENDMAIL/ANY/SHELL for smrsh.
+  * Added dictionary.acc - Stephane Marzloff
+  * Changed the whole configuration over to autoconf
+  * We now use IP numbers in network order internally
+  * Added VersaNet support to checkrad.pl by Versanet Communications,
+    mailed to me by "Yi-Feng Liann" <yifeng@versanetcomm.com>
+  * Added Versanet dictionary
+  * Moved valuepair stuff to valuepair.c
+  * Rewrote config files and user files parsers to be more generic and
+    use the same internal functions so that the quoting rules are
+    all the same.
+  * Moved all radius stuff to lib/, made more generic
+  * proxy uses functions from libradius
+  * long password support (generic functions in libradius)
+  * FIXME: dict.c has problems parsing dictionary.usr, dictionary.tunnel !
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sun, 25 Jul 1999 15:36:39 +0200
+
+radiusd-cistron (1.5.4.3-beta18) experimental; urgency=low
+
+  * Fix the always stripping of realms
+  * Add port number to radius.log
+  * Add phone number to radius.log when logging failed logins
+  * Add -i option (bind to IP address)
+  * Change return value for 'other' in checkrad.pl to '1'
+  * Add password-file caching patch from Jeff Carneal <jeff@apex.net>
+  * Fix broken auth_type_fixup - Bryan Mawhinney <bryanm@is.co.za>
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Fri, 14 May 1999 16:08:56 +0200
+
+radiusd-cistron (1.5.4.3-beta17) experimental; urgency=low
+
+  * Added NULL realm based on an idea by
+    Bastiaan Bakker <Bastiaan.Bakker@lifeline.nl>
+  * Changes for proxying:
+    - detect duplicate requests, resend it with the same ID and vector
+      to the remote radius server
+    - Change proxy-state A/V pair to a 4-byte string without embedded
+      zeros in it, so as not to confuse broken radius servers.
+  * Add casting to (off_t) to lseek offset arg in radzap
+  * Add checking of pw->expire for FreeBSD
+  * Add radutmp location caching: Bryan Mawhinney <bryanm@is.co.za>
+  * Now handles multiple attributes in one Vendor-Specific attribute
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Tue, 27 Apr 1999 14:51:08 +0200
+
+radiusd-cistron (1.5.4.3-beta16) experimental; urgency=low
+
+  * Added SPECIALIX_JETSTREAM_HACK to work around a bug in
+    Specialix Jetstream 8500 24 port firmware.
+  * Added Alan DeKok's cistron-beta15-operator.patch as found on
+    ftp://ftp.striker.ottawa.on.ca/pub/radius/
+  * Added Login-Time check value, see doc/README
+  * Rewrote checkrad.pl:
+    - subroutines to read naspasswd and check Net::Telnet
+    - add possibility to use SNMP_Session perl module instead of snmpget
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Fri, 26 Mar 1999 15:31:57 +0100
+
+radiusd-cistron (1.5.4.3-beta15) experimental; urgency=low
+
+  * Added a DEFAULT realm to /etc/raddb/realms (no idea if this is useful..)
+  * Added LOCAL proxyserver (means none) to /etc/raddb/realms
+  * Added "nostrip" option to /etc/raddb/realms
+  * Changed "-p" option to "-S"; "-p <port>" now allows you to specify
+    the port(s) radiusd listens on.
+  * Fix auth.c:rad_check_password(). auth_item must be present.
+  * Fixed radwho - secured popen(). This could be a BIG SECURITY HOLE
+    when you run radwho as your finger daemon - esp. if it runs as root!!!
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Thu, 21 Jan 1999 17:58:06 +0100
+
+radiusd-cistron (1.5.4.3-beta14) experimental; urgency=low
+
+  * Fix buffer size in proxy.c from 0104 to 1024 :)
+  * On lines with a Password = "bla" line without Auth-Type, add
+    Auth-Type = Local implicitly while parsing the users file
+  * Fix CHAP for both local authentication and proxying (I hope..)
+  * Now Exec-Program-Wait tries to parse output of the program as
+    A/V pairs. Those are added to the reply. Mostly based on the
+    patch from "The light in the dark" <sijaiko@netplus.bg>
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sat, 19 Dec 1998 17:45:15 +0100
+
+radiusd-cistron (1.5.4.3-beta12) experimental; urgency=low
+
+  * Don't store radutmp/radwtmp info for admin logins, or
+    for leased lines going up/down
+  * Integrated latest version of checkrad from www.mdi.ca
+  * Instead of storing only the first part of acct-session-id in radutmp,
+    store the last part since that is more specific.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sat, 28 Nov 1998 17:07:31 +0100
+
+radiusd-cistron (1.5.4.3-beta11) experimental; urgency=low
+
+  * Fix crash in proxy_cleanup()
+  * Some more SIGCHLD fixes.
+  * Fix $(PAM) in Make.inc for files.c
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Tue, 17 Nov 1998 12:09:46 +0100
+
+radiusd-cistron (1.5.4.3-beta10) experimental; urgency=low
+
+  * Fixed some compilation warnings that showed up on certain platforms
+  * Removed rogue USR debugging message
+  * Hopefully fixed passwd problem with Ascend and proxy
+  * Fixed problems with bogus trailing attributes when receiving
+    vendor-specific attributes.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Tue, 10 Nov 1998 00:04:33 +0100
+
+radiusd-cistron (1.5.4.3-beta9) experimental; urgency=low
+
+  * The USR Vendor-Specific stuff should actually work now
+  * USR dictionary included
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sat,  7 Nov 1998 16:30:55 +0100
+
+radiusd-cistron (1.5.4.3-beta8) experimental; urgency=low
+
+  * Fix for Solaris 2.5.1 and signal() in SIGCHLD handler.
+  * Fix "suppress trailing zero" code in attrprint.c
+  * Fixed vendor-specific attributes which I broke in beta7
+  * Fixed radwtmp code which I broke in beta6
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Fri,  6 Nov 1998 19:29:47 +0100
+
+radiusd-cistron (1.5.4.3-beta7) experimental; urgency=low
+
+  * Make sure that send_buffer and recv_buffer are properly aligned
+    by declaring them as an array of ints. Needed for Solaris/Sparc.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Tue,  3 Nov 1998 16:22:00 +0100
+
+radiusd-cistron (1.5.4.3-beta6) experimental; urgency=low
+
+  * Hack in support for accounting "alive" packets.
+  * Support for USR vendor specific attributes.
+  * Moved ASCEND_PORT_HACK so that it doesn't change the port number
+    internally for Authentication packets.
+  * Removed some "no username" complaints as this can happen with
+    initial Start record (usually an "Alive" packet update comes later)
+  * Add $(PAM) to auth.o rule in Make.inc
+  * Added Redhat stuff from Mauricio Andrade <mandrade@mma.com.br>
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Tue,  3 Nov 1998 15:55:40 +0100
+
+radiusd-cistron (1.5.4.3-beta5) experimental; urgency=low
+
+  * Add $(LIBS) to radzap link stage
+  * In attrprint.c, suppress the printing of the trailing zero Ascend
+    gear likes to send (noted by Kris Hunt <suid@chilli.net.au>)
+  * In checkrad.pl:livingston_snmp() make snmpget output matching regexps
+    more general to work with more versions of snmpget
+  * Fix for usrhyper from "James R. Pooton" <james@digisys.net>
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sat, 17 Oct 1998 17:42:48 +0200
+
+radiusd-cistron (1.5.4.3-beta4) experimental; urgency=low
+
+  * Add Pam-Auth attribute (Chris Dent)
+  * Fixes in files.c by Alan DeKok for pair_move2() and empty reply pairs.
+  * Fix in radiusd.c rad_spawn_child() by Alan DeKok to check for duplicate
+    packets in a much better way (compare both ID and vector).
+  * Put some functoins in their own file: auth.c, exec.c
+  * First cut at proxy support in proxy.c
+  * Use new VALUE_PAIR->length everywhere, at least for strvalues.
+  * Added vendor-specific attributes, format as in Livingston Radius 2.1
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Thu,  8 Oct 1998 21:20:49 +0200
+
+radiusd-cistron (1.5.4.3-beta3) experimental; urgency=low
+
+  * Include new checkrad.pl from Shilo Costa. See also
+    http://www.mdi.ca/sysadmin/cistron/
+    Net::Telnet based code by Alexis C. Villalon.
+  * Fix documentation bug checklogin -> checkrad
+  * Now a failed Exec-Program-Wait will really deny access
+  * Added patches from Don Greer <dgreer@austintx.com>, see
+    http://www.austintx.com/~dgreer/cistron-ascend/
+  * Fix sp_expire check for shadow passwd (thanks to Alan Madill)
+  * Patches from Blaz Zupan <blaz@amis.net> for FreeBSD
+  * Folded all four reply-functions into one
+  * Hopefully now Prefix = "P", Group = "group" works properly
+  * Fix uue()
+  * Fix dbm support (Blaz)
+  * Fix signal handler so that children do not kill accounting process.
+  * Now reloads config files on-the-fly after SIGHUP
+  * Added "-A" flag to write a "detail.auth" file.
+  * Make messages in radius.log more consistent
+  * Fix Denial-Of-Service problem - crashing radius with illegal packets
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sat,  4 Jul 1998 15:06:55 +0200
+
+radiusd-cistron (1.5.4.2) experimental; urgency=low
+
+  * Turn off SIGCHLD handler and use waitpid() in rad_check_ts()
+    On some OSes the wait() for the checkrad script failed.
+  * Fix Auth-Type = Crypted-Local
+  * Store porttype in radutmp (backwards compatible)
+  * Fix shadow passwords.
+  * Check expiration date for shadow passwords.
+  * Add %s (Connect-Info) to string en/de coder
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Mon,  5 Jan 1998 14:22:28 +0100
+
+radiusd-cistron (1.5.4.1) experimental; urgency=low
+
+  * Fixed radwho.c
+  * Fixed acct.c to calculate the right accounting response digest
+  * In acct.c, check the accounting request digest.
+  * Added PAM suppport
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sat, 22 Nov 1997 16:43:18 +0100
+
+radiusd-cistron (1.5.4) experimental; urgency=low
+
+  * Now compiles with glibc too
+  * Try to detect if TS only sends logout records and don't complain
+  * Started implementing double login checks through external programs
+    (see checkrad.pl script).
+  * Delete most A/V pairs from reply if Callback-Id is seen
+    (I'm not sure if this is actually OK, but we'll see...)
+  * Fix rc.radiusd script and radwatch to use pid files instead of killall
+  * Set timeout of 5 seconds on rad_getpwnam cache.
+  * Heiko Schlittermann <heiko@lotte.sax.de> provided diffs for:
+    - Added check for return code of the Exec-Program-Wait call and use
+      this as additional criterium if access is permitted or denied.
+    - Install cron.daily script too
+    - Removed race condition concerning handling for SIGCHLD
+    - Added feature: external program called via Exec-Program-Wait may
+      return up to 127 characters via its STDOUT.  These characters
+      are to form an user message if the request is rejected.
+  * Add $INCLUDE directive for "dictionary" file.
+  * Seperated "clients" file into "clients" and "naslist" files.
+  * Allow spaces in usernames, using " " or `\ '
+  * Fixed wild pointer in radzap()
+  * Default for radwo-as-finger is to not show the fullname (privacy)
+  * Implement reliable double-login detection!
+  * Fix lockf (oops - I used it completely in the wrong way!)
+  * Fix rad_check_muli to use read() correctly
+  * Make stdout linebuffered if debug_flag (-x) is set.
+  * Fix Group/Group-Name check for huntgroups file. Found thanks to
+    Christian Oyarzun <oyarzun@marley.wilmington.net>.
+  * Removed CISTRON_COMPAT code. If you really need it, you can turn it
+    on by adding a Port-Message with % escape sequences in the users file.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Tue, 21 Oct 1997 16:01:47 +0200
+
+radiusd-cistron (1.5.3.pre4-4) experimental; urgency=low
+
+  * Fixed Prefix/Suffix stuff in hints file.
+  * Extra consistency check for ComOS reboot records. Sometimes Ascends send
+    bogus records that look a lot like them..
+    Noted by Jens Glaser <jens@regio.net>
+  * Add -p flag to getopt() call
+  * Fix sample users file (User-Message -> Port-Message)
+  * If Password = is set (and not "UNIX"), Auth-Type is always Local
+  * Do not strip everything after a space from the username.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Sat, 19 Jul 1997 14:34:10 +0200
+
+radiusd-cistron (1.5.3.pre4-3) experimental; urgency=low
+
+  * Add Timestamp record to radius accounting records
+  * Also strip NT domain from logfiles if NT_DOMAIN_HACK is defined
+  * Add -p flag to log stripped names into the "details" file.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Fri, 4 Jul 1997 10:29:26 +0200
+
+radiusd-cistron (1.5.3.pre4-2) experimental; urgency=low
+
+  * Added some manual pages.
+  * Fixed Prefix/Suffix support
+  * Commented out example config files
+  * Added debian package files.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Fri, 27 Jun 1997 20:49:31 +0200
+
+radiusd-cistron (1.5.3.pre4-1) experimental; urgency=low
+
+  * Upgraded dictionary to radius-2.01
+  * Added support for Crypt-Password
+  * Cleaned up code in radiusd.c
+  * Added Exec-Program-Wait
+  * Added Prefix/Suffix support
+  * Changed "hints" syntax to resemble "users" more closely
+    Added extra attribute "Hint" that can be set in the "hints" file
+  * Added $INCLUDE directive for users/hints/huntgroups file
+  * DBM "users" file doesn't work at the moment!!
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Fri, 20 Jun 1997 15:26:29 +0200
+
+radiusd-cistron (1.5.3) cistron; urgency=low
+
+  * Exec-Program actually works now.
+  * Somehow no longer core dumps :)
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Mon, 5 May 1997 10:32:17 +0200
+
+radiusd-cistron (1.5.2) cistron; urgency=high
+
+  * Fix radiusd.c to actually _check_ for a password when Auth-Type = System.
+    It just let anyone in :( (it did work with Password = "UNIX" though).
+  * Fix sample users file (Callback-No -> Callback-Number)
+  * Start of Exec-Program support (not finished).
+  * Better Simultaneous-Use checking
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Wed, 19 Feb 1997 12:26:56 +0100
+
+radiusd-cistron (1.5.1) cistron; urgency=low
+
+  * Fixed radzap to allow both "Sport" and plain "port".
+  * acct.c now checks portmaster reboot records (already did that, but it
+    seems that a PM3 sends buggy records).
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Mon, 10 Feb 1997 16:33:38 +0100
+
+radiusd-cistron (1.5) cistron; urgency=low
+
+  * ANSIfied code, changed comment style
+  * Renamed users.c to files.c. Now pre-reads all config files.
+  * DBM support works now
+  * Added new logging routines
+  * Changed utmp format, added better checks
+  * Moved utmp to /var/log
+  * Now supports both wtmp file and RADIUS style logging
+  * Added Simultaneous-Use support.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Fri, 7 Feb 1997 17:56:11 +0100
+
+radiusd-cistron (1.4) cistron; urgency=low
+
+  * Started using ChangeLog
+  * Ported to Solaris, FreeBSD in addition to Linux.
+
+ -- Miquel van Smoorenburg <miquels@cistron.nl>  Wed, 02 Oct 1996 12:27:39 +0200
+
diff --git a/doc/Makefile.in b/doc/Makefile.in
new file mode 100644 (file)
index 0000000..a6bb984
--- /dev/null
@@ -0,0 +1,9 @@
+
+@INCLUDE@ @IQUOTE@../Make.inc@IQUOTE@
+
+all:
+
+install:
+
+clean:
+
diff --git a/doc/PAM b/doc/PAM
new file mode 100644 (file)
index 0000000..fead45f
--- /dev/null
+++ b/doc/PAM
@@ -0,0 +1,56 @@
+
+               PAM Support for Cistron-radiusd
+
+
+0. INTRODUCTION
+
+   PAM support was done by Jeph Blaize. Miguel a.l. Paraz <map@iphil.net>
+   ported it to Cistron-Radius. Chris Dent <cdent@kiva.net> added the
+   Pam-Auth attribute. It is not complete yet but seems to work
+   (for authentication only).
+
+1. USAGE
+
+   Use Auth-Type = Pam in the users file. For backwards compatibility,
+   you can also use Password = "PAM" but, like Password = "UNIX", this
+   is depreciated.
+
+   You can also use ``Pam-Auth = "somestring"'' to specify an entry in
+   /etc/pam.d. The default is "radius".
+
+2. NOTES
+
+   Added the following hacks, see CFLAGS in src/Makefile to activate.
+   Crude support for PAM authentication (-DPAM), User-Password = "PAM".
+
+   Miguel has made PAM changes to the Cistron radiusd, since he now uses
+   it as the basis of many accounting systems. However, according to the
+   PAM experts, calling the pam_start function for each user to be
+   authenticated is a bad idea. Seems to work for him, though.
+
+   Besides, the Pam-Auth attribute only works if pam_start is called
+   everytime anyways ..
+
+3. TODO:
+
+   Real PAM support, figure out how we can write a module that will make
+   it blend in with PAM more seamlessly.  With this, we can replace the
+   DENY_SHELL with something more flexible such as a database.
+
+4. EXAMPLE:
+
+DEFAULT Auth-Type = Pam,  NAS-IP-Address = 206.97.64.5
+       Service-Type = Framed-User,
+       Framed-Protocol = PPP,
+       Framed-IP-Address = 255.255.255.254,
+       Filter-Id = "std.ppp",
+       Framed-MTU = 1500,
+       Framed-Compression = Van-Jacobson-TCP-IP
+DEFAULT Auth-Type = Pam,  Pam-Auth = "radius2", NAS-IP-Address = 127.0.0.1
+       Service-Type = Framed-User,
+       Framed-Protocol = PPP,
+       Framed-IP-Address = 255.255.255.254,
+       Filter-Id = "std.ppp",
+       Framed-MTU = 1500,
+       Framed-Compression = Van-Jacobson-TCP-IP
+
diff --git a/doc/README b/doc/README
new file mode 100644 (file)
index 0000000..07db66a
--- /dev/null
@@ -0,0 +1,316 @@
+
+0. WARNING!
+
+  Cistron Radius now uses autoconf - some of the default directories
+  have changed! Configuration is now by default in /usr/local/etc/raddb,
+  and logfiles are in /usr/local/var/log/ ....
+  See 2. for more info.
+
+1. INTRO
+
+  This is version 1.6-alphaX of the Cistron Radius daemon.
+
+       *** THIS IS AN ALPHA VERSION! IT MIGHT NOT WORK ***
+
+  All code in this server was written from scratch.
+
+  The server is mostly compatible with livingston radiusd-2.01
+  (no menus or s/key support though) but with more feautures, such as:
+
+    o Can limit max. number of simultaneous logins on a per-user basis!
+    o Multiple DEFAULT entries, that can optionally fall-through.
+    o In fact, every entry can fall-through
+    o Deny/permit access based on huntgroup users dials into
+    o Set certain parameters (such as static IP address) based on huntgroup
+    o Extra "hints" file that can select SLIP/PPP/rlogin based on
+      username pattern (Puser or user.ppp is PPP, plain "user" is rlogin etc).
+    o Can execute an external program when user has authenticated (for example
+      to run a sendmail queue).
+    o Can use `$INCLUDE filename' in users and dictionary files
+    o Can act as a proxy server, relaying requests to a remote server
+    o Supports Vendor-Specific attributes
+    o No good documentation at all, just like the original radiusd 1.16!
+
+  Work on real manual pages is progressing slowly. For a large part you
+  can use the documentation of the Livingston 2.01 server. Just remember
+  that using Prefix and Suffix in both the "users" and the (cistron-radiusd
+  specific) "hints" file will give unpredictable results. Well actually
+  it will result in Prefix and Suffix probably not working in the "users"
+  file if you already stripped them off in the "hints" file.
+
+  The documentation of the Livingston server is available on the web at:
+  http://www.livingston.com/Tech/Docs/RADIUS/guide/
+
+  Extra command line flags:
+  o -y: log all login attempts in /var/log/radius.log, include (wrong)
+        password for failed logins.
+  o -z: log the password of successful logins too (STRONLY discouraged).
+
+2. COMPILE
+
+  Ignore this section (2) if you have a pre-installed binary package.
+
+  Radiusd now has autoconf support. This means you have to run
+  ./configure --flags, then run make. You can set the following flags:
+
+  --prefix=            Prefix to install (default: /usr/local)
+  --localstatedir=     Base prefix for the logfiles. Defaults
+                       to PREFIX/var
+  --with-logdir=DIR    Directory for radutmp, radwtmp and radius.log.
+                       Defaults to LOCALSTATEDIR/log
+  --with-radacctdir=DIR        Directory for the detail files. Defaults to
+                       LOGDIR/radacct
+  --sysconfdir         Base prefix for the raddb directory. Defaults to
+                       PREFIX/etc
+  --with-raddbdir=DIR  Configuration files. Defaults to SYSCONFDIR/raddb
+  --with-dbm           Include DBM support (Old-style DBM)
+  --with-ndbm          Include NDBM support
+  --with-pam           Include PAM support
+  --with-ascend-hack   Include Ascend hacks
+  --with-ascend-cpl=N  Set Ascend Channels Per Line to N
+  --with-ntdomain-hack Include NT Domain hack (strip first part of
+                       NT_DOMAIN\loginname if seen)
+  --with-spcj-hack     Include Specialix Jetstream hacks
+  --with-dict-nocase   Make dictionary case-independant
+  --without-dynamic-modules
+                       Turn off dynamic modules even if your
+                       system supports them.
+
+  To get the defaults that Cistron Radius used up to 1.5.4.3-beta18, use:
+
+       ./configure --localstatedir=/var --sysconfdir=/etc
+
+  That means binaries will get installed in /usr/local/{bin,sbin},
+  manpages in /usr/local/man, configuration files in /etc/raddb,
+  and logfiles in /var/log and /var/log/radacct.
+
+  Now type "make". The binaries will be compiled.
+
+  Then you do a "make install". That will install JUST the binaries
+  for now. You need to install the rest by hand like this:
+
+  o Copy the examples in raddb to /etc/raddb and edit+rename the sample files.
+  o If you have a Debian system, you might want to install rc.radiusd
+    as /etc/init.d/radiusd and install startup symlinks with
+    "update-rc.d radiusd defaults".
+  o If you use rc.radiusd, also install radwatch in /usr/local/sbin.
+  o Start radiusd (using /etc/init.d/radiusd start if applicable).
+
+3. USAGE
+
+  You can use last -f /var/log/radwtmp to get last info on all users.
+  You can use "radwho" at any time to find out who's logged in.
+  If you want, you can install "radwho" as /usr/sbin/in.fingerd.
+  Also, the "raduse" program can be very useful to monitor your modem pool.
+
+4. CONFIGURATION FILES
+
+  For every file there is a fully commented example file included, that
+  explains what is does and how to use it. Read those sample files too!
+
+4a. CLIENTS
+
+  Make sure the clients (portmasters, Linux with portslave etc) are set up to
+  use the host radiusd is running on as authentication and accounting host.
+  Configure these clients to use a "radius secret password". For every client,
+  also enter this "secret password" into the file /etc/raddb/clients.
+  See also the manual page for clients(5rad).
+
+4b. NASLIST
+
+  Every NAS (Network Access Server, also known as terminal server) should have
+  an entry in this file with an abbreviated name and the type of NAS it
+  is. Currently Cistron Radius supports the following NAS types:
+
+  Terminal Server                       Type in naslist
+
+  3Com/USR Hiper Arc Total Control      usrhiper
+  3Com/USR NetServer                    netserver
+  3Com/USR TotalControl                 tc
+  Ascend Max 4000 family                max40xx
+  Cisco Access Server family            cisco
+  Cistron PortSlave                     portslave
+  Computone PowerRack                   computone
+  Cyclades PathRAS                      pathras
+  Livingston PortMaster                 livingston
+  Multitech CommPlete Server            multitech
+  Patton 2800 family                    patton
+
+  Usually this is the same list as in the "clients" file, but not every
+  NAS is a client and not every client is a NAS (this will start to make
+  sense if you use radius proxy servers).
+
+4c. NASPASSWD
+
+  If ``checkrad'' needs to login on your terminal server to check who
+  is online on a certain port (i.e. it's not possible to use SNMP or
+  finger) you need to define a loginname and password here.
+
+  This is normally ONLY needed for USR/3Com Total Control, NetServer and
+  Cyclades PathRAS terminal servers!
+
+4c. HINTS
+
+  Customize the /etc/raddb/hints file. This file is used to give users a
+  different login type based on a prefix/suffix of their loginname. For
+  example, logging in as "user" may result in a rlogin session to a Unix
+  system, and logging in as "Puser" could start a PPP session.
+
+4d. HUNTGROUPS
+
+  This is the /etc/raddb/huntgroups file. Here you can define different
+  huntgroups. These can be used to:
+
+    - restrict access to certain huntgroups to certain users/groups of
+      users (define this in the huntgroups file itself)
+    - match a loginname with a huntgroup in /etc/raddb/users. One use
+      for this is to give a user a static IP address based on the
+      huntgroup / Point of Presence  (s)he dials in to.
+
+4e. USERS
+
+  With the original RADIUS server, every user had to be defined in this
+  file. There could be one default entry, where you could for example
+  define that a user not in the radius file would be checked agains the
+  UNIX password file and on succesfull login would get a PPP connection.
+
+  In the new style file, you can define multiple DEFAULT entries. All
+  entries are processed in the order as they appear in the users file.
+  If an entry matches the username, radiusd will stop scanning the users
+  file unless the attribute "Fall-Through = Yes" is set.
+
+  You can uses spaces in usernames by escaping them with \ or by using
+  quotes. For example, "joe user" or joe\ user.
+
+  The Cistron Radiusd does not trim any spaces from a username received
+  from the portmaster (livingston does, in perl notation, $user =~ s/\s+.*//;)
+
+4f. NEW RADIUS ATTRIBUTES (to be used in the USERS file).
+
+  Name                 Type            Descr.
+  ----                 ----            ------
+  Simultaneous-Use     integer         Max. number of concurrent logins
+  Fall-Through         integer         Yes/No
+  Exec-Program         string          program to execute after authentication
+  Exec-Program-Wait    string          ditto, but wait for program to finish
+                                       before sending back auth. reply
+  Login-Time           string          Defines when user may login.
+
+  Exec-Program can take arguments. You can use macros in the arguments:
+
+  Taken from the original request:
+    %p   Port number
+    %n   NAS IP address
+    %u   User name
+    %a   Protocol (SLIP/PPP)
+    %s   Speed (connect string - eg "28800/V42.BIS")
+    %i   Calling Station ID
+
+  Taken from the reply as defined thusfar:
+    %f   Framed IP address
+    %c   Callback-Number
+    %t   MTU
+
+  For example, use the following entry for someone who has BSMTP (queued
+  SMTP) service. "brunq" is the program that runs the SMTP queue.
+
+  robert       Service-Type = Framed-User
+               Exec-Program = "/usr/local/sbin/brunq -h %f delta",
+               Fall-Through = 1
+
+  The output from Exec-Program-Wait is parsed by the radius server. If
+  it looks like Attribute/Value pairs, they are decoded and added to the
+  reply sent to the NAS. This way, you can for example set Session-Timeout.
+
+  For backwards compatibility, if the output doesn't look like valid
+  radius A/V pairs, the output is taken as a message and added to the
+  reply sent to the NAS as Port-Message.
+
+  If Exec-Program-Wait returns a non-zero exit status, access will be
+  denied to the user. With a zero-exit status, access is granted.
+
+  Login-Time defines the time span a user may login to the system. The
+  format of a so-called time string is like the format used by UUCP.
+  A time string may be a list of simple time strings separated by "|" or ",".
+
+  Each simple time string must begin with a day definition. That can be just
+  one day, multiple days, or a range of days separated by a hyphen. A
+  day is Mo, Tu, We, Th, Fr, Sa or Su, or Wk for Mo-Fr. "Any" or "Al"
+  means all days.
+
+  After that a range of hours follows in hhmm-hhmm format.
+
+  For example, "Wk2305-0855,Sa,Su2305-1655".
+
+  Radiusd calculates the number of seconds left in the time span, and
+  sets the Session-Timeout to that number of seconds. So if someones
+  Login-Time is "Al0800-1800" and she logs in at 17:30, Session-Timeout
+  is set to 1800 seconds so that she is kicked off at 18:00.
+
+5. LOG FILES
+
+5a. /var/log/radutmp
+
+  In this file the currently logged in users are held. The program "radwho"
+  reads this file and gives you a summary. Rogue sessions can be deleted
+  from this file with the "radzap" program.
+
+5b. /var/log/radwtmp
+
+  This file is "wtmp" compatible and keeps a history of all radius logins/
+  logouts. This file can be read with the "last" program, and other Unix
+  accounting programs (such as "ac" and "sac") can be used to produce a
+  summary.
+
+5c. /var/log/radius.log
+
+  All RADIUS informational. diagnostic and error messages are logged in
+  this file.  If radiusd has been started with the "-y" flag, all logins
+  attempts will be logged in this file. For failed logins, the wrong password
+  will also be logged.  With the "-z" flag, the passwords for successful
+  logins will be logged as well. That's pretty dangerous though in case
+  anyone unpriviliged ever manages to get access to this file!
+
+5d. /var/log/radacct/<terminal_server>/detail
+
+  This is the original radius logfile, as written by all the livingston
+  radius servers. It's only created if the directory /var/log/radacct exists.
+  The <terminal_server> name is the short name if one is defined in
+  /etc/raddb/naslist.
+
+6.  MORE INFO, SUPPORT
+
+  I know that the documentation provided is sparse. However it is not in
+  the scope of the radius server to provide a guide as to how terminal
+  servers works and how the RADIUS protocol works and is used.
+
+  Unfortunately I do not have too much time myself to answer all questions
+  that might arise through email - you can always try sending me email,
+  ofcourse, but I cannot guarantee a reply, depends on how much time I have.
+
+  The latest version of Cistron Radius is always available from
+  http://www.www.cistron.nl/radius/
+
+  There is a majordomo mailing list hosted by Cistron Internet Services. Send
+  a message with "help" in the body to cistron-radius-request@info.cistron.nl.
+  You can browse the archive of this mailing list at
+  http://info.cistron.nl/archives/cistron-radius/
+
+  There are a few other mailing lists that might offer some help:
+
+  You can also try the the linux-isp mailing list, which on a lot of sites
+  used to be accessible as the newsgroup linux.admin.isp (not anymore).
+  For the mailing list, send a message with "help" in the body to
+  linuxisp-request@friendly.jeffnet.org. Several people on that list are
+  successfully using this software.
+
+  There is a linux-radius list run by miguel a.l. paraz <map@iphil.net>.
+  See http://www.iphil.net/~map/radius/ for details.
+
+  Then ofcourse for general RADIUS questions, especially if you are using
+  Livingston  / Lucent RABU equipment, there is the portmaster-radius mailing
+  list. Send mail to portmaster-radius-request@livingston.com to find
+  out how to subscribe.
+
+
+   README 1.6-alpha2  Miquel van Smoorenburg <miquels@cistron.nl>  11-Aug-1999
diff --git a/doc/README.Y2K b/doc/README.Y2K
new file mode 100644 (file)
index 0000000..61fdd73
--- /dev/null
@@ -0,0 +1,17 @@
+
+                       Cistron Radius and Y2K
+
+
+   I've checked the source code of radiusd-cistron-1.5.4.3-beta15 for
+   obvious Y2K problems (use of tm_year from struct tm for example)
+   and couldn't find any.
+
+   This doesn't mean you can sue me if there happens to be a Y2K problem
+   anyway. It does mean that I am pretty sure Cistron Radius will survive
+   31-12-1999 -> 01-01-2000 and that our ISP business will run uninterrupted.
+
+
+
+
+   README.Y2K  Miquel van Smoorenburg <miquels@cistron.nl>  26-Mar-1999
+
diff --git a/doc/Simultaneous-Use b/doc/Simultaneous-Use
new file mode 100644 (file)
index 0000000..c7047b2
--- /dev/null
@@ -0,0 +1,148 @@
+
+       Cistron-Radius and the Simultaneous-Use parameter.
+
+
+0. INTRODUCTION
+
+  Lots of people want to limt the number of times one user account can
+  login, usually to one. Thi is hard to do with the radius protocol;
+  the nature of the accounting stuff is such that the idea the radius server
+  has about the list of logged-in users might be different from the idea
+  the terminal server has about it.
+
+  However since ComOS 3.7 there is the possibility to get the list of logged
+  in users through SNMP from a portmaster. So if the radius server thinks
+  that someone is trying to login a second time, it is possible to check
+  on the terminal server itself if the first login is indeed still active.
+  Only then access is denied for the second login.
+
+
+1. PREREQUISITES
+
+  You need to have perl installed.
+
+  For SNMP checks, you have 2 options. You can use the `snmpget' program
+  from the cmu-snmp tools. You can probably get precompiled ones,
+  maybe even packaged for your system (Debian/Linux, Redhat/Linux, FreeBSD
+  ports collection etc). The source code is at
+  http://www.net.cmu.edu/projects/snmp/snmpapps/. The Linux-specific
+  version of this is at http://www.gaertner.de/snmp/
+
+  The other option is to install the SNMP_Session and BER modules that
+  come with mrtg - http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html
+  In that case you need no external snmpget program, checkrad will
+  speak SNMP directly.
+
+  The checkroutine for USR/3Com Total Control, NetServer racks and
+  Cyclades PathRAS uses the Net::Telnet module from CPAN, at least version
+  3.00. If you need that, obtain it from your local CPAN mirror (or see
+  http://www.perl.com/CPAN/). The checkrad.pl perl script will autodetect if
+  that module is installed.
+
+2. USAGE.
+
+  It works by adding the `check' parameter "Simultaneous-Use" to the entry
+  for a users or DEFAULT in /etc/raddb/users. It should be at least one;
+  it defines the maximum number of users logged in with the same account name.
+  For example:
+
+  #
+  # Simultaneous use restrictions.
+  #
+  DEFAULT Group = "staff", Simultaneous-Use = 4
+          Fall-Through = 1
+  DEFAULT Group = "business", Simultaneous-Use = 2
+          Fall-Through = 1
+  DEFAULT Simultaneous-Use = 1
+          Fall-Through = 1
+
+
+  NOTE!!! The "Simultaneous-Use" parameter is in the "check" A/V pairs,
+          and not in the Reply A/V pairs (it _is_ a check).
+
+3. IMPLEMENTATION
+
+  As soon as the radius server thinks it sees a double login, it executes the
+  perl script /usr/local/sbin/checkrad (or /usr/sbin/checkrad, it checks for
+  the presence of both and in that order). This script queries the terminal
+  server too see if the user is indeed logged in.
+
+  The script uses SNMP for Livingston Portmasters, Ciscos and Patton,
+  finger for Portslave, Computone and Ascend, and Net::Telnet for USR/3Com
+  TC and Cyclades PathRAS.
+
+  Since the script has been witten in perl, it's easy to adjust for
+  any type of terminal server. There are implementations in the script for
+  checks using SNMP, finger, and telnet, so it should be easy to add
+  your own check routine if your terminal server is not supported yet.
+
+  You can find the script in the file src/checkrad.pl.
+
+  You need to set the correct type in the file /etc/raddb/naslist so that
+  checkrad KNOWS how it should interrogate the terminal server. At this
+  time you can define the following types:
+
+  type        Vendor      Uses method     needs               Need naspasswd
+  ====        ======      ===========     =====               ==============
+  cisco       Cisco       SNMP            SNMP                No
+  computone   Computone   finger          -                   No
+  livingston  Livingston  SNMP            SNMP                No       [1]
+  max40xx     Ascend      finger          -                   No
+  multitech   Multitech   SNMP            SNMP                No
+  netserver   USR/3com    telnet          CPAN Net::Telnet    Yes
+  pathras     Cyclades    telnet          CPAN Net::Telnet    Yes
+  patton      Patton      SNMP            SNMP                No
+  portslave   ?           finger          -                   No
+  tc          USR/3com    telnet          CPAN Net::Telnet    Yes
+  usrhiper    USR/3com    SNMP            SNMP                No       [2]
+  versanet    VersaNet    SNMP            SNMP                No
+
+  [1] Needs at least ComOS 3.5, SNMP enabled.
+  [2] Set "Reported Port Desity" to 256 (default)
+
+4. IF IT DOESN'T WORK
+
+  You can edit the `checkrad' perl script and turn on debugging. Then
+  watch the debug file. The `radius.log' file also gives some hints.
+
+  Note that you need to add the Simultaneous-Login parameter to the
+  check item (first line), not the reply item.
+
+  A portmaster numbers the ports in the SNMP protocol from 1 to XX. The
+  perl script tries to find out which ones relates to S0 and calculates the
+  SNMP offset from that. However with a PM3 there is a "gap" in the S ports.
+  With a European ISDN-30 line, S30 and S31 do not exist. In the US, I think
+  that S23 might be skipped (try a `show sessions' on the portmaster). The
+  perl script catches the European situation, but needs to be adjusted for
+  the American situation. Perhaps this can be made reasonably automatic by
+  looking at what timezone we're in :)
+
+5. CAVEATS
+
+  This solution checks the radutmp file. This file is kept up-to-date from
+  the Accounting records the NAS sends. Since some NASes delay these records
+  for quite some time, it is possible to get a double login by loggin in
+  twice at _exactly_ the same time (plus or minus the mentioned delay time),
+  since neither of the logins are registered yet.
+
+  The solution would be to create a small 1-minute cache of Authentication
+  records, that is also checked for double login attempts. Perhaps in the
+  next version.
+
+  When implementing this one thing was considered the most important: when
+  trying to detect double logins, we always try to err on the safe side. So
+  in rare cases, a double login is possible but we try never to limit access
+  for a legitimate login.
+
+6. PROBLEMS WITH DROPPED CONNECTIONS
+
+  Our PM3, with 2 ISDN-30 lines coming into it, had the habit of sometimes
+  dropping connections. In a few cases, the portmaster thought the session was
+  still alive so if the user tried to login again, he or she was denied access.
+  In our case, this problem was caused by a bad PRI line from the phone
+  company.
+
+  We tried to compensate this by setting the Idle-Timeout to 15 minutes. That
+  way, even if a user did get locked out the portmaster would clear the rogue
+  session within 15 minutes and the user could login again.
+
diff --git a/doc/builddbm.8rad b/doc/builddbm.8rad
new file mode 100644 (file)
index 0000000..be1279f
--- /dev/null
@@ -0,0 +1,19 @@
+.TH BUILDDBM 8 "20 Januari 1997" "" "Cistron Radius Daemon"
+.SH NAME
+builddbm -- build DBM file from RADIUS users file.
+.SH SYNOPSIS
+.B builddbm
+.SH DESCRIPTION
+This utility is used to build a DBM file (in DBM or NDBM format) from
+the radius \fIusers\fP file to save memory.
+.PP
+Usage of this utility is only encouraged if you don't use multiple
+DEFAULT entries (or only at the end of the \fIusers\fP file) and
+you have more then 500 entries in the \fIusers\fP file. Normally,
+\fBradiusd\fP reads the \fIusers\fP file into memory at startup. With
+very large files this may cost too many resources and it may then
+be wiser to use a DBM file to save memory.
+.SH SEE ALSO
+radiusd(8), users(5rad).
+.SH AUTHOR
+Miquel van Smoorenburg, miquels@cistron.nl.
diff --git a/doc/cache b/doc/cache
new file mode 100644 (file)
index 0000000..013844c
--- /dev/null
+++ b/doc/cache
@@ -0,0 +1,545 @@
+Cistron Password Caching 
+
+Acknowledgements
+
+Thanks to Alan DeKok for the initial idea, to Dr. Bob Pilgrim for
+implementation strategies, and to Miquel for putting it into cistron.
+
+What does this caching do?
+
+It will add the capability to cache several of the system files that
+are used often by cistron radius. These include: /etc/passwd, /etc/shadow
+(if necessary), and /etc/group.
+
+By caching the information in these files and storing it in a VERY efficient
+hash table, authentication lookups are sped up many times over. So, the
+short answer is that your authentication requests will be faster if you use
+caching, assuming you're using System authenication now. Read on for the
+long answer.
+
+How do I use it?
+
+Compile radiusd as you normally would, and then run it with the "-c" option.
+Then, if you want to monitor how the caching is doing (errors and such),
+'grep HASH /var/log/radius.log'.
+
+What are the advantages?
+
+Tremendous speed increase in authentication request handling. Orders of
+magnitude, literally.
+
+What are the disadvantages?
+
+As with anything else, there are a couple of trade-offs. However, these are
+quite modest, IMHO.
+
+First, memory consumption of your radiusd process will go up somewhat over
+normal operation. Depending on the size of your files, it could take several
+megabytes of RAM to build the hash table properly. However, I have gone to
+great lengths to ensure that there are no memory leaks. The size of the
+daemon process should stay constant, or grow linearly with the size of your
+system files. If you notice otherwise, send me an email with lots of detail
+about your system and I'll see what I can find.
+
+Second, you should kill -HUP the main radiusd process every so often out of
+cron. The reason for this is because the daemon will need to rebuild the
+cache to get passwords that you have changed for existing users. You will
+not have to -HUP it for new users in /etc/passwd to get authenticated, as if
+it can't find the user in the hash, it will automatically revert to the old
+(slow) lookup methods [getpwnam()]. However, if you change the password for
+a user, and the hash table contains that user but with the old password, it
+will simply think that the user is supplying the wrong password and deny
+them access. One thing I'd like to point out is that rebuilding the hash
+with the -HUP takes less than a second with our ~1MB /etc/passwd and shadow
+files. The slowest part of the -HUP is caused by the gethostby*() functions.
+All in all, a -HUP reconfig is virtually instant on our solaris boxes, and
+takes about 15 seconds on standard linux 2.x machines.
+
+Why was it written?
+
+In examining our radius servers, I noticed that there were several things
+slowing down an authentication requests. Please note that some of these
+things will depend on what you are doing in your raddb/users file, however,
+most of the things we were doing were quite common, so I feel that others
+may have similar setups. In any case, I'll go thru exactly what we were
+seeing, and how caching fixes it.
+
+Authentication Bottlenecks:
+*Group check items calling getgrnam()
+*DEFAULT users with System authentication calling getpwnam()
+*Simultaneous use check reading file /var/log/radutmp
+
+First, the auth request comes in, and radius (usually) forks a child to
+handle it. The child will then check the raddb/users file to see if the user
+is explicitly listed there. In our case, most the users were matched off of
+a DEFAULT system entry, meaning they would be looked up in the /etc/passwd
+and /etc/shadow files. However, first, we had to check for a couple of
+groups that aren't allowed access. In our case we had two DEFAULT group
+compare check items, meaning that the getgrnam() system call was called
+twice for every authentication request. Considering that the /etc/group file
+is not so large, that wasn't a huge factor. However, the /etc/group file is
+stored on disk, and was accessed through system calls, meaning it had to be
+opened and searched until a matching group was found (twice), slowing down
+authentication requestions somewhat.
+
+Ok, so we've established that there's a getgrnam() call for each DEFAULT
+user you have with a group check item. If you don't have any such DEFAULTs,
+no problem, you don't have those calls. However, nearly 99% of you probably
+have a line like the following in your raddb/users file, leading into the
+next bottleneck: DEFAULT Auth-Type = System, Simultaneous-Use = 1
+
+What does that mean? It means, for every auth request that comes in for
+which we don't have an explicit match in our raddb/users file, lookup the
+user in /etc/passwd and/or /etc/shadow using getpwnam() and getspwnam()
+system calls. So what's so bad about that? It works right? Well, yes, but
+it's inefficient because of the way getpwnam() works.
+
+Think for a second about what getpwnam() has to do. It is a linear search
+algorithm through an unsorted list stored on disk. It is an O(N) algorithm,
+for you computer science folks (barring any caching build into the function
+by particular OSs). So, basically, what it does is open the /etc/passwd
+file, start at line one, compare that user to the user we're looking for,
+and if there's no match, go to the next line and repeat. That means that on
+average, every auth request you're taking requires opening and reading half
+of your /etc/passwd file. Worst case is when a user not in the file is
+looked up, as you search the entire file without a match. Best case is when
+the user is the first one in the file, and average is in the middle
+somewhere.
+
+Are you saying, that doesn't sound so bad? Well, then perhaps caching
+isn't for you. In our case, we had a ~15,000 line passwd file, and anywhere
+from 20-40,000 logins daily. The getpwnam() call was taking by far the
+majority of the radius daemon's time, resulting in fairly poor
+authentication performance.
+
+NOTE:  radutmp caching is disabled for now until we can find a better way 
+to do it.  Still, this next paragraph indicates why it needs doing.
+
+Lastly, if you're using the wonderful simultaneous-use check item in cistron
+radius, you have another disk lookup to perform on your /var/log/radutmp
+file (actually, caching of this file just came available in b17. glad
+somebody else noticed it :) What happens is, if the user is authenticated
+properly, the daemon then opens the radutmp file, reads until it hits a line
+matching the user currently requesting authentication, and then either
+allows or denies access based on the presense or absense of a match. Thus,
+in the majority of cases, you read the entire file in for every
+authentication request (assuming that most of your users aren't trying to
+steal service from you :) .
+
+So, we've identified the problems. If you really care about how caching
+addresses those problems, keep reading.
+
+How does it work?
+
+The code will first open your /etc/passwd file and runs through it hashing
+all the usernames into a numeric index into my hash table. It then creates
+an entry into the hashtable at that index for every user in the file.
+Currently, it caches username, password, gid, and uid in the entry. Then, if
+you have shadow passwords, it will open your /etc/shadow file and put the
+passwords into the entry corresponding with the appropriate user. It is this
+hash table that allows us to eliminate the getpwnam() bottleneck. Read below
+for how to test it.
+
+Next, it will read the /etc/group file and build a singly linked list of it.
+It's not as fast as the hash, but the group file is usually small enough
+that it wouldn't make a difference. Just brining it into RAM should be good
+enough. This takes care of the getgrnam() bottleneck.
+
+NOTE:  Again, radutmp caching is disabled.  Disregard this next paragraph.
+
+Finally, it reads the /var/log/radutmp file and marks every user listed as
+logged in with a login variable stored in their hash entry. Then, every time
+a user logs in or out, that variable is updated so that we can avoid reading
+in /var/log/radutmp.
+
+So what, right? Well, understand that for every user lookup done on a
+system, you have currently to read half of your passwd file. Thus, the
+number of comparisons done per getpwnam() is the number of lines in your
+passwd file divided by two. So do 'wc -l /etc/passwd', divide that by two,
+and that's the number of comparisons done per user lookup on your system
+right now.
+
+Using the hash table method, I have achieved user lookups in RAM in near
+constant time. That is, using my passwd files (everyone's is different,
+obviously), I could find a user in the hash in 1.0673 comparisons (on
+average). Being that 1.0 is the lowest number of comparisons possible,
+that's a pretty significant thing. Again, for the computer science people,
+the hash function and table are wide enough such that 87.4% of users are
+stored singly in a bucket, 11.7% are stored with two users in a bucket, 0.8%
+are stored with 3 users in the bucket, and 0.03% are stored with more than 3
+users per bucket. That means that 87% of your lookups are done in one
+comparison, versus the number you got when you did the 'wc -l /etc/passwd' /
+2 above. This discussion has also neglected the fact that RAM searches are
+many, many times faster than disk searches. We'll let it speak for itself.
+
+But, you don't have to take my word for it. I have a test program that I've
+written that can show you the difference on your own system between the
+speed in lookups using the hash and getpwnam().  You can find the program
+cachetest.c at this end of this file.  Simply save it to cachetest.c and
+and compile it with: 
+
+gcc -o cachetest ./cachetest.c
+
+What it does is read in your passwd file, build a hash of it, and then
+perform the number of lookups you specify either with getpwnam() or using
+the hash lookup functions.
+
+Before performing tests, please note that the larger the passwd file, the
+larger the disparity between the two test methods. So you'll get a more
+accurate depiction of what the code will do for your system by running it
+on a passwd file on your radius server.
+
+I'd recommend doing the following tests with it:
+
+# Perform 1,000 lookups using getpwnam()
+./cachetest 1000 -s
+
+# Perform 1,000 lookups using the hash
+./cachetest 1000
+
+My guess, no real significant difference in the time taken to complete each
+of those. Next test.
+
+# Perform 10,000 lookups using getpwnam()
+./cachetest 10000 -s
+
+# Perform 10,000 lookups using the hash
+./cachetest 10000
+
+Unless you've got a real fast machine, you should have noticed a little bit
+of difference between the two that time. Next test
+
+# Perform 50,000 lookups using getpwnam()
+./cachetest 50000 -s
+
+# Perform 50,000 lookups using the hash
+./cachetest 50000
+
+Unless you have a cray, I'm real confident you noticed a difference that
+time. If the 50,000 user lookup didn't extraordinarily long on your system,
+try this last test.
+
+# Perform 100,000 lookups using getpwnam()
+./cachetest 100000 -s
+
+# Perform 100,000 lookups using the hash
+./cachetest 100000
+
+No doubt, you saw the difference here. Unless you want to be old and gray
+when you finish the getpwnam() tests, I'd recommend not going higher than
+100,000. Still, it's up to you. Go as high as you want on the hash test.
+1,000,000 hash lookups are done in about a second on my pentium 400 running
+linux.
+
+How will it help my radius server?
+
+Well, assuming you can live with the disadvantages listed above, it'll make
+it faster. If you haven't run the tests in the above section, I'd recommend
+doing so.
+
+Is it stable?
+
+As far as I can tell, yes. We've run it on both linux and solaris maches for
+about two weeks now, and had zero problems. If you notice a bug, by all
+means, let me know and I'll see if I can get a fix out. However, if you
+notice system degrading problems with it, you can always turn it off by
+running radiusd without the "-c" argument.
+
+Ok, that's it. If you made it this far, I'm impressed. Let me know what you
+think...
+
+jeff@apex.net
+
+--------------------------------------------------------------------------
+
+/*
+ * cachetest.c:  Tests performance difference between user lookups in
+ * the hash table vs. getpwnam()
+ *
+ * All users in the passwd/shadow files are stored in a hash table.
+ * the hash lookup is VERY fast,  generally 1.0673 comparisons per
+ * lookup.  For the unitiated, that's blazing.  You can't have less
+ * than one comparison, for example.
+ *
+ *     (c) 1999 Author - Jeff Carneal, Apex Internet Services, Inc.
+ */    
+/* 
+       COMPILE:  gcc -o cachetest cachetest.c
+*/
+#include<stdio.h>
+#include<fcntl.h>
+#include<grp.h>
+#include<unistd.h>
+#include<stdlib.h>
+#include<errno.h>
+#include<ctype.h>
+#include<sys/stat.h>
+#include<sys/types.h>
+#include<string.h>
+
+/* Misc definitions */
+#define BUFSIZE  1024
+#define MAXUSERNAME 20
+#define HASHTABLESIZE 100000
+#define PASSWDFILE "/etc/passwd"
+
+/* Structure definitions */
+struct mypasswd {
+       char    *pw_name;       /* user name */
+       char    *pw_passwd;     /* user password */
+       uid_t   pw_uid;         /* user id */
+       gid_t   pw_gid;         /* group id */
+       int     loggedin;       /* number of logins */
+       struct mypasswd *next;  /* next */
+};
+
+/* Function prototypes */
+int buildHashTable(void);
+struct mypasswd *findHashUser(const char *user);
+int storeHashUser(struct mypasswd *new, int index);
+int hashUserName(const char *s);
+int doHashTest(int numusers, unsigned long numlookups);
+int usage(void);
+
+/* Make the tables global since so many functions rely on them */
+static struct mypasswd *hashtable[HASHTABLESIZE];
+static struct mygroup *grphead = NULL;
+
+char allusers[HASHTABLESIZE][MAXUSERNAME];
+int usegetpwnam=0;
+
+int main(int argc, char** argv) {
+       int numusers=0;
+       unsigned long numlookups=0;
+       
+       if(argc<2) {
+               usage();
+       }
+               
+       if(isdigit(argv[1][0])) {
+               numlookups = atoi(argv[1]);     
+       } else {
+               usage();
+       }
+       if((argv[2] != NULL) && !strncmp(argv[2],"-s",2)) {
+               usegetpwnam = 1;
+       }
+       
+       memset((char *)allusers, 0, MAXUSERNAME*HASHTABLESIZE);
+
+       numusers = buildHashTable();
+       if(numusers < 0) {
+               printf("HASH:  Error building hash table!  Quitting...\n");
+               exit(1);
+       }
+
+       doHashTest(numusers, numlookups);
+       printf("Done!\n\n");
+
+}
+
+/* Builds the hash table up by storing passwd/shadow fields
+ * in memory.  Returns -1 on failure, 0 on success.
+ */
+int buildHashTable(void) {
+       FILE *passwd, *shadow;
+       char buffer[BUFSIZE];
+       char idtmp[10];
+       char username[MAXUSERNAME];
+       char *ptr, *bufptr;
+       int len, hashindex, numread=0;
+       struct mypasswd *new, *cur, *next;
+
+       memset((char *)username, 0, MAXUSERNAME);
+
+       /* Init hash array */
+       memset((struct mypasswd *)hashtable, 0, (HASHTABLESIZE*(sizeof(struct mypasswd *))));
+
+       if( (passwd = fopen(PASSWDFILE, "r")) == NULL) {
+               printf("HASH:  Can't open file %s:  %s", PASSWDFILE, strerror(errno));
+               return -1;
+       } else {
+               while(fgets(buffer, BUFSIZE , passwd) != (char *)NULL) {
+                       numread++;
+
+                       bufptr = buffer;
+                       /* Get usernames from password file */
+                       for(ptr = bufptr; *ptr!=':'; ptr++);
+                       len = ptr - bufptr;
+                       if((len+1) > MAXUSERNAME) {
+                               printf("HASH:  Username too long in line: %s", buffer);
+                       }
+                       strncpy(username, buffer, len);
+                       username[len] = '\0';
+                       if(numread < HASHTABLESIZE) {
+                               strncpy(allusers[numread-1], username, MAXUSERNAME);
+                       }
+
+                       /* Hash the username */
+                       hashindex = hashUserName(username);     
+                       /*printf("%s:%d\n", username, hashindex);*/
+       
+                       /* Allocate space for structure to go in hashtable */
+                       if((new = (struct mypasswd *)malloc(sizeof(struct mypasswd))) == NULL) {
+                               printf("HASH:  Out of memory!");
+                               return -1;
+                       }
+                       memset((struct mypasswd *)new, 0, sizeof(struct mypasswd));
+
+                       /* Put username into new structure */
+                       if((new->pw_name = (char *)malloc(strlen(username)+1)) == NULL) {
+                               printf("HASH:  Out of memory!");
+                               return -1;
+                       }
+                       strncpy(new->pw_name, username, strlen(username)+1);
+
+                       /* Put passwords into array, if not shadowed */
+                       /* Get passwords from password file (shadow comes later) */
+                       ptr++;
+                       bufptr = ptr;
+                       while(*ptr!=':')
+                               ptr++;
+
+                       #if defined(NOSHADOW)
+                       /* Put passwords into new structure (*/
+                       len = ptr - bufptr;
+                       if((new->pw_passwd = (char *)malloc(len+1)) == NULL) {
+                               printf("HASH:  Out of memory!");
+                               return -1;
+                       }
+                       strncpy(new->pw_passwd, bufptr, len);
+                       new->pw_passwd[len] = '\0';
+                       #endif /* NOSHADOW */  
+
+                       /* 
+                   * Put uid into structure.  Not sure why, but 
+                        * at least we'll have it later if we need it
+                        */
+                       ptr++;
+                       bufptr = ptr;
+                       while(*ptr!=':')
+                               ptr++;
+                       len = ptr - bufptr;
+                       strncpy(idtmp, bufptr, len);
+                       idtmp[len] = '\0';
+                       new->pw_uid = (uid_t)atoi(idtmp);       
+
+                       /* 
+                   * Put gid into structure.  
+                        */
+                       ptr++;
+                       bufptr = ptr;
+                       while(*ptr!=':')
+                               ptr++;
+                       len = ptr - bufptr;
+                       strncpy(idtmp, bufptr, len);
+                       idtmp[len] = '\0';
+                       new->pw_gid = (gid_t)atoi(idtmp);       
+
+                       /* 
+                        * We're skipping name, home dir, and shell
+                        * as I can't think of any use for storing them
+                        */
+
+                       /*printf("User:  %s, UID:  %d, GID:  %d\n", new->pw_name, new->pw_uid, new->pw_gid);*/
+                       /* Store user in the hash */
+                       storeHashUser(new, hashindex);
+               }       /* End while(fgets(buffer, BUFSIZE , passwd) != (char *)NULL) { */
+       } /* End if */
+       fclose(passwd);
+
+       return numread;
+}
+
+/*
+ * Looks up user in hashtable.  If user can't be found, returns 0.  
+ * Otherwise returns a pointer to the structure for the user
+ */
+struct mypasswd *findHashUser(const char *user) {
+
+       struct mypasswd *cur;
+       int index;
+
+       /* first hash the username and get the index into the hashtable */
+       index = hashUserName(user);
+
+       cur = hashtable[index];
+
+       while((cur != NULL) && (strcmp(cur->pw_name, user))) {
+               cur = cur->next;
+       }
+
+       if(cur) {
+               return cur;
+       }
+
+       return (struct mypasswd *)0;
+
+}
+
+/* Stores the username sent into the hashtable */
+int storeHashUser(struct mypasswd *new, int index) {
+
+       /* store new record at beginning of list */
+       new->next = hashtable[index];
+       hashtable[index] = new;
+
+       return 1;
+}
+
+/* Hashes the username sent to it and returns index into hashtable */
+int hashUserName(const char *s) {
+     unsigned long hash = 0;
+
+     while (*s != '\0') {
+         hash = hash * 7907 + (unsigned char)*s++;
+               }
+
+     return (hash % HASHTABLESIZE);
+}              
+
+int doHashTest(int numusers, unsigned long numlookups) {
+       int i, numlookedup = 0;
+
+       /* Use pokey getpwnam() syscall to find users */
+       if(usegetpwnam) {
+               printf("\nUsing getpwnam() lookup for %d user lookups over %d users found\n\n", numlookups, numusers);
+               while(numlookedup < numlookups) {
+                       for(i=0; i<numusers; i++) {
+                               if(numlookedup >= numlookups) 
+                                       return 0;
+
+                               if(allusers[i] != NULL)  {
+                                       getpwnam(allusers[i]);
+                                       numlookedup++;
+                               }
+                       }
+               }
+
+       /* Use blazing fast hash method to find user */
+       } else {
+               printf("\nUsing hash lookup for %d user lookups over %d users found\n\n", numlookups, numusers);
+               while(numlookedup < numlookups) {
+                       for(i=0; i<numusers; i++) {
+                               if(numlookedup >= numlookups) 
+                                       return 0;
+
+                               if(allusers[i] != NULL)  {
+                                       findHashUser(allusers[i]);
+                                       numlookedup++;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+int usage() {
+       printf("\nUsage:  ./cachetest #lookups [-s]\n");
+       printf("\n\tPerform 50,000 lookups using the hash method");
+       printf("\n\tEx:  ./cachetest 50000\n");
+       printf("\n\tPerform 50,000 lookups using the getpwnam() syscall");
+       printf("\n\tEx:  ./cachetest 50000 -s\n\n");
+       exit(1);
+
+}
diff --git a/doc/cisco b/doc/cisco
new file mode 100644 (file)
index 0000000..e01f705
--- /dev/null
+++ b/doc/cisco
@@ -0,0 +1,32 @@
+
+               Cisco IOS 11.x and Radius
+
+For Cisco 11.1, you normally use
+
+   aaa new-model
+   aaa authentication ppp radppp if-needed radius
+   aaa authorization network radius none
+   aaa accounting network wait-start radius
+
+to get the Cisco to talk to a radius server.
+
+With IOS 11.3, you need to add:
+
+   aaa accounting update newinfo
+
+If you want the IP address of the user to show up in the radutmp file
+(and thus, the output of "radwho").
+
+This is because with IOS 11.3, the Cisco first sends a "Start" accounting
+packet without the IP address included. By setting "update newinfo" it
+will send an account "Alive" packet which updates the information. Cistron
+Radius understands the "Alive" packet since 1.5.4.3-beta7.
+
+
+Als you might see a lot of "duplicates" in the logfile. That can be
+fixed by
+
+   aaa accounting network wait radius
+   radius-server timeout 3
+
+
diff --git a/doc/clients.5rad b/doc/clients.5rad
new file mode 100644 (file)
index 0000000..cc565c9
--- /dev/null
@@ -0,0 +1,28 @@
+.TH CLIENTS 5 "15 September 1997"
+.SH NAME
+clients \- RADIUS clients file
+.SH DESCRIPTION
+The \fIclients\fP file resides in the radius database directory,
+by default \fI/etc/raddb\fP. It contains a list of RADIUS clients.
+Every line starting with a hash sign
+.RB (' # ')
+is treated as comment and ignored.
+.PP
+Each line of the file contains two white-space delimited fields.
+.IP client hostname
+The RADIUS clients hostname This may be a plain hostname, or a
+dotted-quad IP address.
+.IP secret
+This is the so-called "shared secret" that is held between a RADIUS
+server and client. It is used to encrypt passwords in RADIUS packets,
+and also for authentication. You need to configure the same secret
+on the client (terminal server) as in this file.
+.PP
+The
+.I clients
+file is read by \fBradiusd\fP on startup only.
+.SH FILES
+.I /etc/raddb/clients
+.SH "SEE ALSO"
+.BR radiusd (8),
+.BR naslist (5rad)
diff --git a/doc/naslist.5rad b/doc/naslist.5rad
new file mode 100644 (file)
index 0000000..ac0873c
--- /dev/null
@@ -0,0 +1,34 @@
+.TH NASLIST 5 "17 May 1999"
+.SH NAME
+naslist \- RADIUS naslist file
+.SH DESCRIPTION
+The \fInaslist\fP file resides in the radius database directory,
+by default \fI/etc/raddb\fP. It contains a list of RADIUS network access
+servers (NASes).
+Every line starting with a hash sign
+.RB (' # ')
+is treated as comment and ignored.
+.PP
+Each line of the file contains three white-space delimited fields.
+.IP client hostname
+The NAS hostname. This may be a plain hostname, or a
+dotted-quad IP address.
+.IP shortname
+This field is optional, and declares a short alias for the NAS.
+It is used in the \fI/var/log/radwtmp\fP accounting file, and to
+build the directory name for the accounting \fIdetail\fP file.
+.IP NAStype
+Type of NAS (terminalserver). This can be \fIcisco\fP, \fIcomputone\fP,
+\fIlivingston\fP, \fImultitech\fP, \fImax40xx\fP, \fInetserver\fP,
+\fIpathras\fP, \fIpatton\fP, \fIportslave\fP, \fItc\fP, \fIusrhiper\fP or
+\fIother\fP. This is passed to the external \fBchecklogin\fP program when
+it is called to detect double logins.
+.PP
+The
+.I naslist
+file is read by \fBradiusd\fP on startup only.
+.SH FILES
+.I /etc/raddb/naslist
+.SH "SEE ALSO"
+.BR radiusd (8),
+.BR clients (5rad)
diff --git a/doc/processing_users_file b/doc/processing_users_file
new file mode 100644 (file)
index 0000000..88feb02
--- /dev/null
@@ -0,0 +1,40 @@
+
+
+               How is the USERS file processed?
+
+
+After the items of a request have been mangled by the "hints" and
+"huntgroups" files, the users file is processed.
+
+A request has initially an empty check list and an empty reply list
+attached to it. So each request has 3 A/V pairlists associated with it
+
+- the request list (as originated from the terminal server)
+- the check list   (initially empty)
+- the reply list   (initially empty)
+
+For every entry in the users file, the Username VP (Value-Pair) is checked.
+If it matches or it is a DEFAULT entry, a check pairlist is created
+(call it tmpcheck) by adding the check pairlist of the current usersfile
+entry to the check pairlist of the request. If an attribute is already
+present in the check pairlist of the request it will not be changed
+(see files.c:movepair).
+
+Then the request pairlist is compared with the tmpcheck pairlist. If
+all items match (except for password-related items at this time!)
+the following actions are taken:
+
+- The reply pairlist of the usersfile entry is appended to the reply
+  pairlist of the request
+- The check pairlist of the request is replaced by the tmpcheck pairlist
+  (this is the same as: the check pairlist from the usersfile entry is
+   appended to the pairlist of the request)
+
+Then a check is made to see if the reply pairlist contains an A-V pair
+of "Fall-Through = Yes". If so, the next entry in the usersfile is processed
+as above. If not, we stop processing the users file.
+
+Then after all this is done, the Authentication information is filtered
+from the check pairlist, the password of the users is checked, and we
+send a reply back to the terminal server.
+
diff --git a/doc/proxy b/doc/proxy
new file mode 100644 (file)
index 0000000..43a20dc
--- /dev/null
+++ b/doc/proxy
@@ -0,0 +1,72 @@
+
+               Cistron-Radius as a proxy radius server.
+
+
+0. INTRODUCTION
+
+  It is now possible to use Cistron Radius as a proxy radius server. This
+  means that it can consult a remote radius server to validate a user.
+  This is handy for roaming setups, or for renting ports to someone else.
+
+1. FILES
+
+  If a user logs in as username@realm, the "realm" part is looked up in
+  the file /etc/raddb/realms. The format of this file is, for now:
+
+  realm                remoteserver[:port]     options
+
+  All accounting data for proxied requests does NOT get stored in the
+  standard logfiles, but in a seperate directory. The name of this
+  directory is the name of the remote radius server, and if you want you
+  can define a nickname for it in /etc/raddb/naslist just as for normal NASes.
+
+  You need to add the hostname and secret for the remote server in the
+  file /etc/raddb/clients. On the remote server you need to add the
+  hostname of your server and the same secret to /etc/raddb/clients as well.
+
+  The realm "DEFAULT" (without the quotes) matches all realms.
+
+  If you set the remoteserver to "LOCAL", the request will be handled
+  locally as usual, without sending it to a remote radius server.
+
+  The realm "NULL" matches any requests WITHOUT a realm.
+
+  Normally the @realm is stripped from the username before sending it on
+  to the remote radius server. If you add the keyword "nostrip" to the
+  options, the @realm suffix will not be stripped.
+
+2. WHAT HAPPENS
+
+  The exact thing that happens is this:
+
+  - A user logs in with an @realm suffix
+  - The hints file gets processed as usual
+  - The user is checked against the huntgroups file. At this point
+    the user _might_ already be rejected.
+  - The realm is looked up in the realms file. If it isn't defined,
+    the users file is processed normally.
+  - The realm suffix is stripped from the username unless "nostrip" was
+    set, and the request is sent to a remote radius server. Note that
+    any stripping done in the hints file doesn't have an effect on the
+    username sent to the remote radius server.
+  - The remote server replies with ACK or REJECT
+
+    On ACK:       The initial Auth-Type is set to Accept
+    On REJECT:    The initial Auth-Type is set to Reject
+
+    The remote server also replies with a set of attributes. For security,
+    all attributes are stripped except:
+
+    Service-Type
+    Framed-Protocol
+    Filter-Id
+    Framed-MTU
+    Framed-Compression
+    Login-Service
+    Reply-Message
+    Session-Timeout
+    Idle-Timeout
+    Port-Limit
+
+    Then the users file is processed as usual.
+
diff --git a/doc/radiusd.8 b/doc/radiusd.8
new file mode 100644 (file)
index 0000000..90ca4e8
--- /dev/null
@@ -0,0 +1,160 @@
+.TH RADIUSD 8 "21 March 1999" "" "Cistron Radius Daemon"
+.SH NAME
+radiusd -- Authentication, Authorization and Accounting server
+.SH SYNOPSIS
+.B radiusd
+.RB [ \-A ]
+.RB [ \-S ]
+.RB [ \-a
+.IR accounting_directory ]
+.RB [ \-b ]
+.RB [ \-c ]
+.RB [ \-d
+.IR config_directory ]
+.RB [ \-f ]
+.RB [ \-i
+.IR ip-address ]
+.RB [ \-l
+.IR log_directory ]
+.RB [ \-p
+.IR port ]
+.RB [ \-s ]
+.RB [ \-v ]
+.RB [ \-x ]
+.RB [ \-y ]
+.RB [ \-z ]
+.SH DESCRIPTION
+This is the Cistron implementation of the well known
+.B radius
+server program. It is based on \fILivingston's\fP radius version 1.16.
+Even though this program is largely compatible with \fILivingston's\fP
+radius version 2.0, it's \fBnot\fP based on any part of that code.
+.PP
+\fBRADIUS\fP is a protocol spoken between an access server, typically
+a device connected to several modems or ISDN lines, and a \fBradius\fP
+server. When a user connects to the access server, (s)he is asked for
+a loginname and a password. This information is then sent to the \fBradius\fP
+server. The server replies with "access denied", or "access OK". In the
+latter case login information is sent along, such as the IP address in
+the case of a PPP connection.
+.PP
+The access server also sends login and logout records to the \fBradius\fP
+server so accounting can be done. These records are kept for each terminal
+server seperately in a file called \fBdetail\fP, and in the \fIwtmp\fP
+compatible logfile \fB/var/log/radwtmp\fP.
+.SH OPTIONS
+
+.IP \-A
+Write a file \fIdetail.auth\fP in addition to the standard \fBdetail\fP file
+in the same directory. This file will contain all the authentication-request
+records. This can be useful for debugging, but not for normal operation.
+
+.IP \-S
+Write the stripped usernames (without prefix or suffix) in the \fIdetail\fP
+file instead of the raw record as received from the terminal server.
+
+.IP "\-a \fIaccounting directory\fP"
+This defaults to \fI/var/log/radacct\fP. If that directory exists,
+\fBradiusd\fP will write an ascii accounting record into a detail file for
+every login/logout recorded. The location of the detail file is
+\fIacct_dir/\fP\fBterminal_server\fP\fI/detail\fP.
+
+.IP "\-l \fIlogging directory\fP"
+This defaults to \fI/var/log\fP. \fBRadiusd\fP writes a logfile here called
+\fIradius.log\fP. It contains informational and error messages, and optionally
+a record of every login attempt (for aiding an ISP's helpdesk). The
+special argument \fIstdout\fP causes the information to get written
+to the standard output instead.
+
+.IP "\-d \fIconfig directory\fP"
+Defaults to \fI/etc/raddb\fP. \fBRadiusd\fP looks here for its configuration
+files such as the \fIdictionary\fP and the \fIusers\fP files.
+
+.IP "\-i \fIip-address\fP"
+Defines which IP addres to bind to for sending and receiving packets-
+useful for multi-homed hosts.
+
+.IP \-b
+If the \fBradius\fP server binary was compiled with \fIdbm\fP support,
+this flag tells it to actually \fIuse\fP the database files instead of the
+flat \fIusers\fP file.
+
+.IP \-c
+This is still an \fIexperimental\fP feature.
+Cache the password, group and shadow files in a hash-table in memory.
+This makes the radius process use a bit more memory, but username
+lookups in the password file are \fImuch\fP faster.
+.IP
+After every change in the real password file (user added, password changed)
+you need to send a \fBSIGHUP\fP to the radius server to let it re-read
+its configuration and the password/group/shadow files !
+
+.IP \-f
+Do not fork, stay running as a foreground process.
+
+.IP "\-p \fIport\fP"
+Normally radiusd listens on the ports specified in \fI/etc/services\fP
+(radius and radacct). With this option radiusd listens on the specified
+port for authentication requests and on the specified port +1 for
+accounting requests.
+
+.IP \-s
+Normally, the server forks a seperate process for accounting, and a seperate
+process for every authentication request. With this flag the server will not
+do that. It won't even "daemonize" (auto-background) itself.
+
+.IP \-x
+Debug mode. In this mode the server will print details of every request
+on it's \fBstderr\fP output. Most useful in combination with \fB-s\fP.
+You can specify this option 2 times (-x -x or -xx) to get a bit more
+debugging output.
+
+.IP \-y
+Write details about every authentication request in the
+\fIradius.log\fP file.
+
+.IP \-z
+Include the password in the \fIradius.log\fP file \fBeven\fP for successful
+logins. \fIThis is very insecure!\fP.
+
+.SH CONFIGURATION
+\fBRadiusd\fP uses 6 configuration files. Each file has it's own manpage
+describing the format of the file. These files are:
+.IP dictionary
+This file is usually static. It defines all the possible RADIUS attributes
+used in the other configuration files. You don't have to modify it.
+.IP clients
+Contains the IP address and a secret key for every client that wants
+to connect to the server.
+.IP naslist
+Contains an entry for every NAS (Network Access Server) in the network. This
+is not the same as a client, especially if you have \fBradius\fP proxy server
+in your network. In that case, the proxy server is the client and it sends
+requests for different NASes.
+.IP
+It also contains a abbreviated name for each
+terminal server, used to create the directory name where the \fBdetail\fP
+file is written, and used for the \fB/var/log/radwtmp\fP file. Finally
+it also defines what type of NAS (Cisco, Livingston, Portslave) the NAS is.
+.IP hints
+Defines certain hints to the radius server based on the users's loginname
+or other attributes sent by the access server. It also provides for
+mapping user names (such as Pusername -> username). This provides the
+functionality that the \fILivingston 2.0\fP server has as "Prefix" and
+"Suffix" support in the \fIusers\fP file, but is more general. Ofcourse
+the Livingston way of doing things is also supported, and you can even use
+both at the same time (within certain limits).
+.IP huntgroups
+Defines the huntgroups that you have, and makes it possible to restrict
+access to certain huntgroups to certain (groups of) users.
+.IP users
+Here the users are defined. On a typical setup, this file mainly contains
+DEFAULT entries to process the different types of logins, based on hints
+from the hints file. Authentication is then based on the contents of
+the UNIX \fI/etc/passwd\fP file. However it is also possible to define all
+users, and their passwords, in this file.
+.SH SEE ALSO
+builddbm(8rad), users(5rad), huntgroups(5rad), hints(5rad),
+clients(5rad), dictionary(5rad).
+.SH AUTHOR
+Miquel van Smoorenburg, miquels@cistron.nl.
diff --git a/doc/radlast.1 b/doc/radlast.1
new file mode 100644 (file)
index 0000000..939c9a1
--- /dev/null
@@ -0,0 +1 @@
+.so man7/undocumented.7
diff --git a/doc/radtest.1 b/doc/radtest.1
new file mode 100644 (file)
index 0000000..939c9a1
--- /dev/null
@@ -0,0 +1 @@
+.so man7/undocumented.7
diff --git a/doc/raduse.1 b/doc/raduse.1
new file mode 100644 (file)
index 0000000..939c9a1
--- /dev/null
@@ -0,0 +1 @@
+.so man7/undocumented.7
diff --git a/doc/radwatch.8 b/doc/radwatch.8
new file mode 100644 (file)
index 0000000..939c9a1
--- /dev/null
@@ -0,0 +1 @@
+.so man7/undocumented.7
diff --git a/doc/radwho.1 b/doc/radwho.1
new file mode 100644 (file)
index 0000000..939c9a1
--- /dev/null
@@ -0,0 +1 @@
+.so man7/undocumented.7
diff --git a/doc/radzap.1 b/doc/radzap.1
new file mode 100644 (file)
index 0000000..939c9a1
--- /dev/null
@@ -0,0 +1 @@
+.so man7/undocumented.7
diff --git a/raddb/Makefile.in b/raddb/Makefile.in
new file mode 100644 (file)
index 0000000..a6bb984
--- /dev/null
@@ -0,0 +1,9 @@
+
+@INCLUDE@ @IQUOTE@../Make.inc@IQUOTE@
+
+all:
+
+install:
+
+clean:
+
diff --git a/raddb/clients b/raddb/clients
new file mode 100644 (file)
index 0000000..927ec04
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# clients      This file contains a list of clients which are allowed to
+#              make authentication requests and their encryption key.
+#
+#              Description of the fields:
+#
+#              * The first field is a valid hostname or IP address
+#                for the client.
+#              * The second field (seperated by blanks or tabs) is the 
+#                encryption key.
+
+# Client Name          Key
+#----------------      ----------
+#portmaster1.isp.com   testing123
+#portmaster2.isp.com   testing123
+#proxyradius.isp2.com  TheirKey
+localhost              testing123
+
diff --git a/raddb/dictionary b/raddb/dictionary
new file mode 100644 (file)
index 0000000..4a20739
--- /dev/null
@@ -0,0 +1,249 @@
+#
+# Updated 07-Nov-1998 to RFC 2138 and RFC 2139
+#
+#      This file contains dictionary translations for parsing
+#      requests and generating responses.  All transactions are
+#      composed of Attribute/Value Pairs.  The value of each attribute
+#      is specified as one of 4 data types.  Valid data types are:
+#
+#      string - 0-253 octets
+#      ipaddr - 4 octets in network byte order
+#      integer - 32 bit value in big endian order (high byte first)
+#      date - 32 bit value in big endian order - seconds since
+#                                      00:00:00 GMT,  Jan.  1,  1970
+#
+#      Enumerated values are stored in the user file with dictionary
+#      VALUE translations for easy administration.
+#
+#      Example:
+#
+#      ATTRIBUTE         VALUE
+#      ---------------   -----
+#      Framed-Protocol = PPP
+#      7               = 1     (integer encoding)
+#
+
+#
+#      Include compatibility dictionary for older users file. Move this
+#      directive to the end of the file if you want to see the old names
+#      in the logfiles too.
+#
+$INCLUDE dictionary.compat
+$INCLUDE dictionary.livingston
+#$INCLUDE dictionary.tunnel
+#$INCLUDE dictionary.usr
+#$INCLUDE dictionary.ascend
+
+#
+#      Following are the proper new names. Use these.
+#
+ATTRIBUTE      User-Name               1       string
+ATTRIBUTE      Password                2       string
+ATTRIBUTE      CHAP-Password           3       string
+ATTRIBUTE      NAS-IP-Address          4       ipaddr
+ATTRIBUTE      NAS-Port-Id             5       integer
+ATTRIBUTE      Service-Type            6       integer
+ATTRIBUTE      Framed-Protocol         7       integer
+ATTRIBUTE      Framed-IP-Address       8       ipaddr
+ATTRIBUTE      Framed-IP-Netmask       9       ipaddr
+ATTRIBUTE      Framed-Routing          10      integer
+ATTRIBUTE      Filter-Id               11      string
+ATTRIBUTE      Framed-MTU              12      integer
+ATTRIBUTE      Framed-Compression      13      integer
+ATTRIBUTE      Login-IP-Host           14      ipaddr
+ATTRIBUTE      Login-Service           15      integer
+ATTRIBUTE      Login-TCP-Port          16      integer
+ATTRIBUTE      Reply-Message           18      string
+ATTRIBUTE      Callback-Number         19      string
+ATTRIBUTE      Callback-Id             20      string
+ATTRIBUTE      Framed-Route            22      string
+ATTRIBUTE      Framed-IPX-Network      23      ipaddr
+ATTRIBUTE      State                   24      string
+ATTRIBUTE      Class                   25      string
+ATTRIBUTE      Vendor-Specific         26      string
+ATTRIBUTE      Session-Timeout         27      integer
+ATTRIBUTE      Idle-Timeout            28      integer
+ATTRIBUTE      Termination-Action      29      integer
+ATTRIBUTE      Called-Station-Id       30      string
+ATTRIBUTE      Calling-Station-Id      31      string
+ATTRIBUTE      NAS-Identifier          32      string
+ATTRIBUTE      Proxy-State             33      string
+ATTRIBUTE      Login-LAT-Service       34      string
+ATTRIBUTE      Login-LAT-Node          35      string
+ATTRIBUTE      Login-LAT-Group         36      string
+ATTRIBUTE      Framed-AppleTalk-Link   37      integer
+ATTRIBUTE      Framed-AppleTalk-Network 38     integer
+ATTRIBUTE      Framed-AppleTalk-Zone   39      string
+
+ATTRIBUTE      Acct-Status-Type        40      integer
+ATTRIBUTE      Acct-Delay-Time         41      integer
+ATTRIBUTE      Acct-Input-Octets       42      integer
+ATTRIBUTE      Acct-Output-Octets      43      integer
+ATTRIBUTE      Acct-Session-Id         44      string
+ATTRIBUTE      Acct-Authentic          45      integer
+ATTRIBUTE      Acct-Session-Time       46      integer
+ATTRIBUTE       Acct-Input-Packets     47      integer
+ATTRIBUTE       Acct-Output-Packets    48      integer
+ATTRIBUTE      Acct-Terminate-Cause    49      integer
+ATTRIBUTE      Acct-Multi-Session-Id   50      string
+ATTRIBUTE      Acct-Link-Count         51      integer
+
+ATTRIBUTE      CHAP-Challenge          60      string
+ATTRIBUTE      NAS-Port-Type           61      integer
+ATTRIBUTE      Port-Limit              62      integer
+ATTRIBUTE      Login-LAT-Port          63      integer
+
+ATTRIBUTE      Connect-Info            77      string
+
+#
+#      Experimental Non Protocol Attributes used by Cistron-Radiusd
+#
+ATTRIBUTE      Huntgroup-Name          221     string
+ATTRIBUTE      User-Category           1029    string
+ATTRIBUTE      Group-Name              1030    string
+ATTRIBUTE      Simultaneous-Use        1034    integer
+ATTRIBUTE      Strip-User-Name         1035    integer
+ATTRIBUTE      Fall-Through            1036    integer
+ATTRIBUTE      Add-Port-To-IP-Address  1037    integer
+ATTRIBUTE      Exec-Program            1038    string
+ATTRIBUTE      Exec-Program-Wait       1039    string
+ATTRIBUTE      Hint                    1040    string
+ATTRIBUTE      Pam-Auth                1041    string
+ATTRIBUTE      Login-Time              1042    string
+
+#
+#      Non-Protocol Attributes
+#      These attributes are used internally by the server
+#
+ATTRIBUTE      Expiration                21    date
+ATTRIBUTE      Auth-Type               1000    integer
+ATTRIBUTE      Menu                    1001    string
+ATTRIBUTE      Termination-Menu        1002    string
+ATTRIBUTE      Prefix                  1003    string
+ATTRIBUTE      Suffix                  1004    string
+ATTRIBUTE      Group                   1005    string
+ATTRIBUTE      Crypt-Password          1006    string
+ATTRIBUTE      Connect-Rate            1007    integer
+
+#
+#      Integer Translations
+#
+
+#      User Types
+
+VALUE          Service-Type            Login-User              1
+VALUE          Service-Type            Framed-User             2
+VALUE          Service-Type            Callback-Login-User     3
+VALUE          Service-Type            Callback-Framed-User    4
+VALUE          Service-Type            Outbound-User           5
+VALUE          Service-Type            Administrative-User     6
+VALUE          Service-Type            NAS-Prompt-User         7
+VALUE          Service-Type            Call-Check              10
+
+#      Framed Protocols
+
+VALUE          Framed-Protocol         PPP                     1
+VALUE          Framed-Protocol         SLIP                    2
+
+#      Framed Routing Values
+
+VALUE          Framed-Routing          None                    0
+VALUE          Framed-Routing          Broadcast               1
+VALUE          Framed-Routing          Listen                  2
+VALUE          Framed-Routing          Broadcast-Listen        3
+
+#      Framed Compression Types
+
+VALUE          Framed-Compression      None                    0
+VALUE          Framed-Compression      Van-Jacobson-TCP-IP     1
+
+#      Login Services
+
+VALUE          Login-Service           Telnet                  0
+VALUE          Login-Service           Rlogin                  1
+VALUE          Login-Service           TCP-Clear               2
+VALUE          Login-Service           PortMaster              3
+
+#      Status Types
+
+VALUE          Acct-Status-Type        Start                   1
+VALUE          Acct-Status-Type        Stop                    2
+VALUE          Acct-Status-Type        Alive                   3
+VALUE          Acct-Status-Type        Accounting-On           7
+VALUE          Acct-Status-Type        Accounting-Off          8
+
+#      Authentication Types
+
+VALUE          Acct-Authentic          RADIUS                  1
+VALUE          Acct-Authentic          Local                   2
+
+#      Termination Options
+
+VALUE          Termination-Action      Default                 0
+VALUE          Termination-Action      RADIUS-Request          1
+
+#      NAS Port Types, available in 3.3.1 and later
+
+VALUE          NAS-Port-Type           Async                   0
+VALUE          NAS-Port-Type           Sync                    1
+VALUE          NAS-Port-Type           ISDN                    2
+VALUE          NAS-Port-Type           ISDN-V120               3
+VALUE          NAS-Port-Type           ISDN-V110               4
+
+#      Acct Terminate Causes, available in 3.3.2 and later
+
+VALUE           Acct-Terminate-Cause    User-Request            1
+VALUE           Acct-Terminate-Cause    Lost-Carrier            2
+VALUE           Acct-Terminate-Cause    Lost-Service            3
+VALUE           Acct-Terminate-Cause    Idle-Timeout            4
+VALUE           Acct-Terminate-Cause    Session-Timeout         5
+VALUE           Acct-Terminate-Cause    Admin-Reset             6
+VALUE           Acct-Terminate-Cause    Admin-Reboot            7
+VALUE           Acct-Terminate-Cause    Port-Error              8
+VALUE           Acct-Terminate-Cause    NAS-Error               9
+VALUE           Acct-Terminate-Cause    NAS-Request             10
+VALUE           Acct-Terminate-Cause    NAS-Reboot              11
+VALUE           Acct-Terminate-Cause    Port-Unneeded           12
+VALUE           Acct-Terminate-Cause    Port-Preempted          13
+VALUE           Acct-Terminate-Cause    Port-Suspended          14
+VALUE           Acct-Terminate-Cause    Service-Unavailable     15
+VALUE           Acct-Terminate-Cause    Callback                16
+VALUE           Acct-Terminate-Cause    User-Error              17
+VALUE           Acct-Terminate-Cause    Host-Request            18
+
+#VALUE         Tunnel-Type             L2TP                    3
+#VALUE         Tunnel-Medium-Type      IP                      1
+
+#
+#      Non-Protocol Integer Translations
+#
+
+VALUE          Auth-Type               Local                   0
+VALUE          Auth-Type               System                  1
+VALUE          Auth-Type               SecurID                 2
+VALUE          Auth-Type               Crypt-Local             3
+VALUE          Auth-Type               Reject                  4
+VALUE          Auth-Type               ActivCard               4
+
+#
+#      Cistron extensions
+#
+VALUE          Auth-Type               Pam                     253
+VALUE          Auth-Type               Accept                  254
+
+#
+#      Experimental Non-Protocol Integer Translations for Cistron-Radiusd
+#
+VALUE          Fall-Through            No                      0
+VALUE          Fall-Through            Yes                     1
+VALUE          Add-Port-To-IP-Address  No                      0
+VALUE          Add-Port-To-IP-Address  Yes                     1
+
+#
+#      Configuration Values
+#      comment out these two lines to turn account expiration off
+#
+
+VALUE          Server-Config           Password-Expiration     30
+VALUE          Server-Config           Password-Warning        5
+
diff --git a/raddb/dictionary.acc b/raddb/dictionary.acc
new file mode 100644 (file)
index 0000000..6aeee91
--- /dev/null
@@ -0,0 +1,229 @@
+#
+# dictionary.acc
+#              Dictionary for Acc/Newbridge, models Tigris, Amazon, etc.
+#              Written by Stephane Marzloff <smarzloff@carif-idf.org>
+#              based on specifications available through ftp and the web.
+#
+# Version:     @(#)dictionary.acc  1.00  smarzloff  21-Jun-1999
+#
+
+VENDOR Acc     5
+
+#
+# Acc specific
+ATTRIBUTE      Acc-Reason-Code                 1       integer         Acc
+ATTRIBUTE      Acc-Ccp-Option                  2       integer         Acc
+ATTRIBUTE      Acc-Input-Errors                3       integer         Acc
+ATTRIBUTE      Acc-Output-Errors               4       integer         Acc
+ATTRIBUTE      Acc-Access-Partition            5       string          Acc
+ATTRIBUTE      Acc-Customer-Id                 6       string          Acc
+ATTRIBUTE      Acc-Ip-Gateway-Pri              7       ipaddr          Acc
+ATTRIBUTE      Acc-Ip-Gateway-Sec              8       ipaddr          Acc
+ATTRIBUTE      Acc-Route-Policy                9       integer         Acc
+ATTRIBUTE      Acc-ML-MLX-Admin-State          10      integer         Acc
+ATTRIBUTE      Acc-ML-Call-Threshold           11      integer         Acc
+ATTRIBUTE      Acc-ML-Clear-Threshold          12      integer         Acc
+ATTRIBUTE      Acc-ML-Damping-Factor           13      integer         Acc
+ATTRIBUTE      Acc-Tunnel-Secret               14      string          Acc
+ATTRIBUTE      Acc-Clearing-Cause              15      integer         Acc
+ATTRIBUTE      Acc-Clearing-Location           16      integer         Acc
+ATTRIBUTE      Acc-Service-Profile             17      string          Acc
+ATTRIBUTE      Acc-Request-Type                18      integer         Acc
+ATTRIBUTE      Acc-Bridging-Support            19      integer         Acc
+ATTRIBUTE      Acc-Apsm-Oversubscribed         20      integer         Acc
+ATTRIBUTE      Acc-Acct-On-Off-Reason          21      integer         Acc
+ATTRIBUTE      Acc-Tunnel-Port                 22      integer         Acc
+ATTRIBUTE      Acc-Dns-Server-Pri              23      ipaddr          Acc
+ATTRIBUTE      Acc-Dns-Server-Sec              24      ipaddr          Acc
+ATTRIBUTE      Acc-Nbns-Server-Pri             25      ipaddr          Acc
+ATTRIBUTE      Acc-Nbns-Server-Sec             26      ipaddr          Acc
+ATTRIBUTE      Acc-Dial-Port-Index             27      integer         Acc
+ATTRIBUTE      Acc-Ip-Compression              28      integer         Acc
+ATTRIBUTE      Acc-Ipx-Compression             29      integer         Acc
+ATTRIBUTE      Acc-Connect-Tx-Speed            30      integer         Acc
+ATTRIBUTE      Acc-Connect-Rx-Speed            31      integer         Acc
+ATTRIBUTE      Acc-Modem-Modulation-Type       32      string          Acc
+ATTRIBUTE      Acc-Modem-Error-Protocol        33      string          Acc
+ATTRIBUTE      Acc-Callback-Delay              34      integer         Acc
+ATTRIBUTE      Acc-Callback-Num-Valid          35      string          Acc
+ATTRIBUTE      Acc-Callback-Mode               36      integer         Acc
+ATTRIBUTE      Acc-Callback-CBCP-Type          37      integer         Acc
+ATTRIBUTE      Acc-Dialout-Auth-Mode           38      integer         Acc
+ATTRIBUTE      Acc-Dialout-Auth-Password       39      string          Acc
+ATTRIBUTE      Acc-Dialout-Auth-Username       40      string          Acc
+ATTRIBUTE      Acc-Access-Community            42      integer         Acc
+
+VALUE          Acc-Reason-Code         No-reason-No-Failure            0
+VALUE          Acc-Reason-Code         Resource-shortage               1
+VALUE          Acc-Reason-Code         Session-already-open            2
+VALUE          Acc-Reason-Code         Too-many-RADIUS-users           3
+VALUE          Acc-Reason-Code         No-authentification-server      4
+VALUE          Acc-Reason-Code         No-authentification-response    5
+VALUE          Acc-Reason-Code         No-accounting-server            6
+VALUE          Acc-Reason-Code         No-accounting-response          7
+VALUE          Acc-Reason-Code         Access-Denied                   8
+VALUE          Acc-Reason-Code         Temporary-buffer-shortage       9
+VALUE          Acc-Reason-Code         Protocol-error                  10
+VALUE          Acc-Reason-Code         Invalid-attribute               11
+VALUE          Acc-Reason-Code         Invalid-service-type            12
+VALUE          Acc-Reason-Code         Invalid-framed-protocol         13
+VALUE          Acc-Reason-Code         Invalid-attribute-value         14
+VALUE          Acc-Reason-Code         Invalid-user-information        15
+VALUE          Acc-Reason-Code         Invalid-IP-address              16
+VALUE          Acc-Reason-Code         Invalid-integer-syntax          17
+VALUE          Acc-Reason-Code         Invalid-NAS-port                18
+VALUE          Acc-Reason-Code         Requested-by-user               19
+VALUE          Acc-Reason-Code         Network-disconnect              20
+VALUE          Acc-Reason-Code         Service-interruption            21
+VALUE          Acc-Reason-Code         Physical-port-error             22
+VALUE          Acc-Reason-Code         Idle-timeout                    23
+VALUE          Acc-Reason-Code         Session-timeout                 24
+VALUE          Acc-Reason-Code         Administrative-reset            25
+VALUE          Acc-Reason-Code         NAS-reload-or-reset             26
+VALUE          Acc-Reason-Code         NAS-error                       27
+VALUE          Acc-Reason-Code         NAS-request                     28
+VALUE          Acc-Reason-Code         Undefined-reason-given          29
+VALUE          Acc-Reason-Code         Conflicting-attributes          30
+VALUE          Acc-Reason-Code         Port-limit-exceeded             31
+VALUE          Acc-Reason-Code         Facility-not-available          32
+VALUE          Acc-Reason-Code         Internal-config-error           33
+VALUE          Acc-Reason-Code         Bad-route-specification         34
+VALUE          Acc-Reason-Code         Access-Partition-bind-failure   35
+VALUE          Acc-Reason-Code         Security-violation              36
+VALUE          Acc-Reason-Code         Request-type-conflict           37
+VALUE          Acc-Reason-Code         Configuration-disallowed        38
+VALUE          Acc-Reason-Code         Missing-attribute               39
+VALUE          Acc-Reason-Code         Invalid-request                 40
+VALUE          Acc-Reason-Code         Missing-parameter               41
+VALUE          Acc-Reason-Code         Invalid-parameter               42
+VALUE          Acc-Reason-Code         Call-cleared-with-cause         43
+VALUE          Acc-Reason-Code         Inopportune-config-request      44
+VALUE          Acc-Reason-Code         Invalid-config-parameter        45
+VALUE          Acc-Reason-Code         Missing-config-parameter        46
+VALUE          Acc-Reason-Code         Incompatible-service-profile    47
+VALUE          Acc-Reason-Code         Administrative-reset            48
+VALUE          Acc-Reason-Code         Administrative-reload           49
+VALUE          Acc-Reason-Code         Port-unneeded                   50
+VALUE          Acc-Reason-Code         Port-preempted                  51
+VALUE          Acc-Reason-Code         Port-suspended                  52
+VALUE          Acc-Reason-Code         Service-unavailable             53
+VALUE          Acc-Reason-Code         Callback                        54
+VALUE          Acc-Reason-Code         User-error                      55
+VALUE          Acc-Reason-Code         Host-request                    56
+
+VALUE          Acc-Ccp-Option          Disabled                        1
+VALUE          Acc-Ccp-Option          Enabled                         2
+
+VALUE          Acc-Route-Policy        Funnel                          1
+VALUE          Acc-Route-Policy        Direct                          2
+
+VALUE          Acc-ML-MLX-Admin-State  Enabled                         1
+VALUE          Acc-ML-MLX-Admin-State  Disabled                        2
+
+VALUE          Acc-Clearing-Cause      Cause-unspecified               0
+VALUE          Acc-Clearing-Cause      Unassigned-number               1
+VALUE          Acc-Clearing-Cause      No-route-to-transit-network     2
+VALUE          Acc-Clearing-Cause      No-route-to-destination         3
+VALUE          Acc-Clearing-Cause      Channel-unacceptable            6
+VALUE          Acc-Clearing-Cause      Call-awarded-being-delivered    7
+VALUE          Acc-Clearing-Cause      Normal-clearing                 16
+VALUE          Acc-Clearing-Cause      User-busy                       17
+VALUE          Acc-Clearing-Cause      No-user-responding              18
+VALUE          Acc-Clearing-Cause      User-alerted-no-answer          19
+VALUE          Acc-Clearing-Cause      Call-rejected                   21
+VALUE          Acc-Clearing-Cause      Number-changed                  22
+VALUE          Acc-Clearing-Cause      Non-selected-user-clearing      26
+VALUE          Acc-Clearing-Cause      Destination-out-of-order        27
+VALUE          Acc-Clearing-Cause      Invalid-or-incomplete-number    28
+VALUE          Acc-Clearing-Cause      Facility-rejected               29
+VALUE          Acc-Clearing-Cause      Response-to-status-inquiry      30
+VALUE          Acc-Clearing-Cause      Normal-unspecified-cause        31
+VALUE          Acc-Clearing-Cause      No-circuit-or-channel-available 34
+VALUE          Acc-Clearing-Cause      Network-out-of-order            38
+VALUE          Acc-Clearing-Cause      Temporary-failure               41
+VALUE          Acc-Clearing-Cause      Switching-equipment-congestion  42
+VALUE          Acc-Clearing-Cause      Access-information-discarded    43
+VALUE          Acc-Clearing-Cause      Circuit-or-channel-unavailable  44
+VALUE          Acc-Clearing-Cause      Circuit-or-channed-preempted    45
+VALUE          Acc-Clearing-Cause      Resources-unavailable           47
+VALUE          Acc-Clearing-Cause      Quality-of-service-unavailable  49
+VALUE          Acc-Clearing-Cause      Facility-not-subscribed         50
+VALUE          Acc-Clearing-Cause      Outgoing-calls-barred           52
+VALUE          Acc-Clearing-Cause      Incoming-calls-barred           54
+VALUE          Acc-Clearing-Cause      Bearer-capability-unauthorized  57
+VALUE          Acc-Clearing-Cause      Bearer-capability-not-available 58
+VALUE          Acc-Clearing-Cause      Service-not-available           63
+VALUE          Acc-Clearing-Cause      Bearer-capablity-not-implmented 65
+VALUE          Acc-Clearing-Cause      Channel-type-not-implemented    66
+VALUE          Acc-Clearing-Cause      Facility-not-implemented        69
+VALUE          Acc-Clearing-Cause      Restrcted-digtal-infrmtion-only 70
+VALUE          Acc-Clearing-Cause      Service-not-implemented         79
+VALUE          Acc-Clearing-Cause      Invalid-call-reference          81
+VALUE          Acc-Clearing-Cause      Identified-channel-doesnt-exist 82
+VALUE          Acc-Clearing-Cause      Call-identify-in-use            84
+VALUE          Acc-Clearing-Cause      No-call-suspended               85
+VALUE          Acc-Clearing-Cause      Suspended-call-cleared          86
+VALUE          Acc-Clearing-Cause      Incompatible-destination        88
+VALUE          Acc-Clearing-Cause      Invalid-transit-network-selctin 91
+VALUE          Acc-Clearing-Cause      Invalid-message                 95
+VALUE          Acc-Clearing-Cause      Mandtory-infrmtion-elment-miss  96
+VALUE          Acc-Clearing-Cause      Message-not-implemented         97
+VALUE          Acc-Clearing-Cause      Inopportune-message             98
+VALUE          Acc-Clearing-Cause      Infrmtion-elemnt-not-implmented 99
+VALUE          Acc-Clearing-Cause      Invlid-infrmtion-element-contnt 100
+VALUE          Acc-Clearing-Cause      Message-incompatible-with-state 101
+VALUE          Acc-Clearing-Cause      Recovery-on-timer-expiration    102
+VALUE          Acc-Clearing-Cause      Mndtry-infrmtion-elmnt-lngt-err 103
+VALUE          Acc-Clearing-Cause      Protocol-error                  111
+VALUE          Acc-Clearing-Cause      Interworking                    127
+
+VALUE          Acc-Clearing-Location   Local-or-remote-user            0
+VALUE          Acc-Clearing-Location   Prvte-ntwork-serving-local-user 1
+VALUE          Acc-Clearing-Location   Pblic-ntwork-serving-local-user 2
+VALUE          Acc-Clearing-Location   Transit-network                 3
+VALUE          Acc-Clearing-Location   Prvte-ntwork-serv-remote-user   4
+VALUE          Acc-Clearing-Location   Pblic-ntwork-serv-remote-user   5
+VALUE          Acc-Clearing-Location   International-network           6
+VALUE          Acc-Clearing-Location   Beyond-interworking-point       10
+
+VALUE          Acc-Request-Type        Ring-Indication                 1
+VALUE          Acc-Request-Type        Dial-Request                    2
+VALUE          Acc-Request-Type        User-Authentification           3
+VALUE          Acc-Request-Type        Tunnel-Authentification         4
+
+VALUE          Acc-Bridging-Support    Disabled                        1
+VALUE          Acc-Bridging-Support    Enabled                         2
+
+VALUE          Acc-Apsm-Oversubscribed False                           1
+VALUE          Acc-Apsm-Oversubscribed True                            2
+
+VALUE          Acc-Acct-On-Off-Reason  NAS-Reset                       0
+VALUE          Acc-Acct-On-Off-Reason  NAS-Reload                      1
+VALUE          Acc-Acct-On-Off-Reason  Configuration-Reset             2
+VALUE          Acc-Acct-On-Off-Reason  Configuration-Reload            3
+VALUE          Acc-Acct-On-Off-Reason  Enabled                         4
+VALUE          Acc-Acct-On-Off-Reason  Disabled                        5
+
+VALUE          Acc-Ip-Compression      Disabled                        1
+VALUE          Acc-Ip-Compression      Enabled                         2
+
+VALUE          Acc-Ipx-Compression     Disabled                        1
+VALUE          Acc-Ipx-Compression     Enabled                         2
+
+VALUE          Acc-Callback-Mode       User-Auth                       0
+VALUE          Acc-Callback-Mode       User-Specified-E-164            3
+VALUE          Acc-Callback-Mode       CBCP-Callback                   6
+VALUE          Acc-Callback-Mode       CLI-Callback                    7
+
+VALUE          Acc-Callback-CBCP-Type  CBCP-None                       1
+VALUE          Acc-Callback-CBCP-Type  CBCP-User-Specified             2
+VALUE          Acc-Callback-CBCP-Type  CBCP-Pre-Specified              3
+
+VALUE          Acc-Dialout-Auth-Mode   PAP                             1
+VALUE          Acc-Dialout-Auth-Mode   CHAP                            2
+VALUE          Acc-Dialout-Auth-Mode   CHAP-PAP                        3
+VALUE          Acc-Dialout-Auth-Mode   NONE                            4
+
+VALUE          Acc-Access-Community    PUBLIC                          1
+VALUE          Acc-Access-Community    NETMAN                          2
+
diff --git a/raddb/dictionary.ascend b/raddb/dictionary.ascend
new file mode 100644 (file)
index 0000000..ea55e14
--- /dev/null
@@ -0,0 +1,300 @@
+#
+# Ascend dictionary.
+#
+#              Enable by putting the line "$INCLUDE dictionary.ascend" into
+#              the main dictionary file.
+#
+# Version:     1.00  21-Jul-1997  Jens Glaser <jens@regio.net>
+#              1.01  22-Jan-1998  Tomas Pospisek <tpo@spin.ch>
+#
+
+
+#
+#      Ascend specific extensions
+#      Used by ASCEND MAX/Pipeline products
+#
+ATTRIBUTE      Ascend-FCP-Parameter            119     string
+ATTRIBUTE      Ascend-Modem-PortNo             120     integer
+ATTRIBUTE      Ascend-Modem-SlotNo             121     integer
+ATTRIBUTE      Ascend-Modem-ShelfNo            122     integer
+ATTRIBUTE      Ascend-Call-Attempt-Limit       123     integer
+ATTRIBUTE      Ascend-Call-Block-Duration      124     integer
+ATTRIBUTE      Ascend-Maximum-Call-Duration    125     integer
+ATTRIBUTE      Ascend-Temporary-Rtes           126     integer
+ATTRIBUTE       Tunneling-Protocol              127     integer
+ATTRIBUTE       Ascend-Shared-Profile-Enable    128     integer
+ATTRIBUTE      Ascend-Primary-Home-Agent       129     string
+ATTRIBUTE      Ascend-Secondary-Home-Agent     130     string
+ATTRIBUTE      Ascend-Dialout-Allowed          131     integer
+ATTRIBUTE      Ascend-Client-Gateway           132     ipaddr
+ATTRIBUTE      Ascend-BACP-Enable              133     integer
+ATTRIBUTE      Ascend-DHCP-Maximum-Leases      134     integer
+ATTRIBUTE      Ascend-Client-Primary-DNS       135     ipaddr
+ATTRIBUTE      Ascend-Client-Secondary-DNS     136     ipaddr
+ATTRIBUTE      Ascend-Client-Assign-DNS        137     integer
+ATTRIBUTE      Ascend-User-Acct-Type           138     integer
+ATTRIBUTE      Ascend-User-Acct-Host           139     ipaddr
+ATTRIBUTE      Ascend-User-Acct-Port           140     integer
+ATTRIBUTE      Ascend-User-Acct-Key            141     string
+ATTRIBUTE      Ascend-User-Acct-Base           142     integer
+ATTRIBUTE      Ascend-User-Acct-Time           143     integer
+ATTRIBUTE      Ascend-Assign-IP-Client         144     ipaddr
+ATTRIBUTE      Ascend-Assign-IP-Server         145     ipaddr
+ATTRIBUTE      Ascend-Assign-IP-Global-Pool    146     string
+ATTRIBUTE      Ascend-DHCP-Reply               147     integer
+ATTRIBUTE      Ascend-DHCP-Pool-Number         148     integer
+ATTRIBUTE      Ascend-Expect-Callback          149     integer
+ATTRIBUTE      Ascend-Event-Type               150     integer
+ATTRIBUTE      Ascend-Session-Svr-Key          151     string
+ATTRIBUTE      Ascend-Multicast-Rate-Limit     152     integer
+ATTRIBUTE      Ascend-IF-Netmask               153     ipaddr
+ATTRIBUTE      Ascend-Remote-Addr              154     ipaddr
+ATTRIBUTE      Ascend-Multicast-Client         155     integer
+ATTRIBUTE      Ascend-FR-Circuit-Name          156     string
+ATTRIBUTE      Ascend-FR-LinkUp                157     integer
+ATTRIBUTE      Ascend-FR-Nailed-Grp            158     integer
+ATTRIBUTE      Ascend-FR-Type                  159     integer
+ATTRIBUTE      Ascend-FR-Link-Mgt              160     integer
+ATTRIBUTE      Ascend-FR-N391                  161     integer
+ATTRIBUTE      Ascend-FR-DCE-N392              162     integer
+ATTRIBUTE      Ascend-FR-DTE-N392              163     integer
+ATTRIBUTE      Ascend-FR-DCE-N393              164     integer
+ATTRIBUTE      Ascend-FR-DTE-N393              165     integer
+ATTRIBUTE      Ascend-FR-T391                  166     integer
+ATTRIBUTE      Ascend-FR-T392                  167     integer
+ATTRIBUTE      Ascend-Bridge-Address           168     string
+ATTRIBUTE       Ascend-TS-Idle-Limit            169     integer
+ATTRIBUTE       Ascend-TS-Idle-Mode             170     integer
+ATTRIBUTE      Ascend-DBA-Monitor              171     integer
+ATTRIBUTE      Ascend-Base-Channel-Count       172     integer
+ATTRIBUTE      Ascend-Minimum-Channels         173     integer
+ATTRIBUTE      Ascend-IPX-Route                174     string
+ATTRIBUTE      Ascend-FT1-Caller               175     integer
+ATTRIBUTE      Ascend-Backup                   176     string
+ATTRIBUTE      Ascend-Call-Type                177     integer
+ATTRIBUTE      Ascend-Group                    178     string
+ATTRIBUTE      Ascend-FR-DLCI                  179     integer
+ATTRIBUTE      Ascend-FR-Profile-Name          180     string
+ATTRIBUTE      Ascend-Ara-PW                   181     string
+ATTRIBUTE      Ascend-IPX-Node-Addr            182     string
+ATTRIBUTE      Ascend-Home-Agent-IP-Addr       183     ipaddr
+ATTRIBUTE      Ascend-Home-Agent-Password      184     string
+ATTRIBUTE      Ascend-Home-Network-Name        185     string
+ATTRIBUTE      Ascend-Home-Agent-UDP-Port      186     integer
+ATTRIBUTE      Ascend-Multilink-ID             187     integer
+ATTRIBUTE      Ascend-Num-In-Multilink         188     integer
+ATTRIBUTE      Ascend-First-Dest               189     ipaddr
+ATTRIBUTE      Ascend-Pre-Input-Octets         190     integer
+ATTRIBUTE      Ascend-Pre-Output-Octets        191     integer
+ATTRIBUTE      Ascend-Pre-Input-Packets        192     integer
+ATTRIBUTE      Ascend-Pre-Output-Packets       193     integer
+ATTRIBUTE      Ascend-Maximum-Time             194     integer
+ATTRIBUTE      Ascend-Disconnect-Cause         195     integer
+ATTRIBUTE      Ascend-Connect-Progress         196     integer
+ATTRIBUTE      Ascend-Data-Rate                197     integer
+ATTRIBUTE      Ascend-PreSession-Time          198     integer
+ATTRIBUTE      Ascend-Token-Idle               199     integer
+ATTRIBUTE      Ascend-Token-Immediate          200     integer
+ATTRIBUTE      Ascend-Require-Auth             201     integer
+ATTRIBUTE      Ascend-Number-Sessions          202     string
+ATTRIBUTE      Ascend-Authen-Alias             203     string
+ATTRIBUTE      Ascend-Token-Expiry             204     integer
+ATTRIBUTE      Ascend-Menu-Selector            205     string
+ATTRIBUTE      Ascend-Menu-Item                206     string
+ATTRIBUTE      Ascend-PW-Warntime              207     integer
+ATTRIBUTE      Ascend-PW-Lifetime              208     integer
+ATTRIBUTE      Ascend-IP-Direct                209     ipaddr
+ATTRIBUTE      Ascend-PPP-VJ-Slot-Comp         210     integer
+ATTRIBUTE      Ascend-PPP-VJ-1172              211     integer
+ATTRIBUTE      Ascend-PPP-Async-Map            212     integer
+ATTRIBUTE      Ascend-Third-Prompt             213     string
+ATTRIBUTE      Ascend-Send-Secret              214     string
+ATTRIBUTE      Ascend-Receive-Secret           215     string
+ATTRIBUTE      Ascend-IPX-Peer-Mode            216     integer
+ATTRIBUTE      Ascend-IP-Pool-Definition       217     string
+ATTRIBUTE      Ascend-Assign-IP-Pool           218     integer
+ATTRIBUTE      Ascend-FR-Direct                219     integer
+ATTRIBUTE      Ascend-FR-Direct-Profile        220     string
+ATTRIBUTE      Ascend-FR-Direct-DLCI           221     integer
+ATTRIBUTE      Ascend-Handle-IPX               222     integer
+ATTRIBUTE      Ascend-Netware-timeout          223     integer
+ATTRIBUTE      Ascend-IPX-Alias                224     integer
+ATTRIBUTE      Ascend-Metric                   225     integer
+ATTRIBUTE      Ascend-PRI-Number-Type          226     integer
+ATTRIBUTE      Ascend-Dial-Number              227     string
+ATTRIBUTE      Ascend-Route-IP                 228     integer
+ATTRIBUTE      Ascend-Route-IPX                229     integer
+ATTRIBUTE      Ascend-Bridge                   230     integer
+ATTRIBUTE      Ascend-Send-Auth                231     integer
+ATTRIBUTE      Ascend-Send-Passwd              232     string
+ATTRIBUTE      Ascend-Link-Compression         233     integer
+ATTRIBUTE      Ascend-Target-Util              234     integer
+ATTRIBUTE      Ascend-Maximum-Channels         235     integer
+ATTRIBUTE      Ascend-Inc-Channel-Count        236     integer
+ATTRIBUTE      Ascend-Dec-Channel-Count        237     integer
+ATTRIBUTE      Ascend-Seconds-Of-History       238     integer
+ATTRIBUTE      Ascend-History-Weigh-Type       239     integer
+ATTRIBUTE      Ascend-Add-Seconds              240     integer
+ATTRIBUTE      Ascend-Remove-Seconds           241     integer
+ATTRIBUTE      Ascend-Idle-Limit               244     integer
+ATTRIBUTE      Ascend-Preempt-Limit            245     integer
+ATTRIBUTE      Ascend-Callback                 246     integer
+ATTRIBUTE      Ascend-Data-Svc                 247     integer
+ATTRIBUTE      Ascend-Force-56                 248     integer
+ATTRIBUTE      Ascend-Billing-Number           249     string
+ATTRIBUTE      Ascend-Call-By-Call             250     integer
+ATTRIBUTE      Ascend-Transit-Number           251     string
+ATTRIBUTE      Ascend-Host-Info                252     string
+ATTRIBUTE      Ascend-PPP-Address              253     ipaddr
+ATTRIBUTE      Ascend-MPP-Idle-Percent         254     integer
+ATTRIBUTE      Ascend-Xmit-Rate                255     integer
+
+
+
+# Ascend protocols
+VALUE          Service-Type            Dialout-Framed-User     5
+VALUE          Framed-Protocol         ARA                     255
+VALUE          Framed-Protocol         MPP                     256
+VALUE          Framed-Protocol         EURAW                   257
+VALUE          Framed-Protocol         EUUI                    258
+VALUE          Framed-Protocol         X25                     259
+VALUE          Framed-Protocol         COMB                    260
+VALUE          Framed-Protocol         FR                      261
+VALUE          Framed-Protocol         MP                      262
+VALUE          Framed-Protocol         FR-CIR                  263
+
+
+#
+#      Ascend specific extensions
+#      Used by ASCEND MAX/Pipeline products (see above)
+#
+
+VALUE          Ascend-FR-Direct        FR-Direct-No            0
+VALUE          Ascend-FR-Direct        FR-Direct-Yes           1
+VALUE          Ascend-Handle-IPX       Handle-IPX-None         0
+VALUE          Ascend-Handle-IPX       Handle-IPX-Client       1
+VALUE          Ascend-Handle-IPX       Handle-IPX-Server       2
+VALUE          Ascend-IPX-Peer-Mode    IPX-Peer-Router         0
+VALUE          Ascend-IPX-Peer-Mode    IPX-Peer-Dialin         1
+VALUE          Ascend-Call-Type        Nailed                  1
+VALUE          Ascend-Call-Type        Nailed/Mpp              2
+VALUE          Ascend-Call-Type        Perm/Switched           3
+VALUE          Ascend-FT1-Caller       FT1-No                  0
+VALUE          Ascend-FT1-Caller       FT1-Yes                 1
+VALUE          Ascend-PRI-Number-Type  Unknown-Number          0
+VALUE          Ascend-PRI-Number-Type  Intl-Number             1
+VALUE          Ascend-PRI-Number-Type  National-Number         2
+VALUE          Ascend-PRI-Number-Type  Local-Number            4
+VALUE          Ascend-PRI-Number-Type  Abbrev-Number           5
+VALUE          Ascend-Route-IP         Route-IP-No             0
+VALUE          Ascend-Route-IP         Route-IP-Yes            1
+VALUE          Ascend-Route-IPX        Route-IPX-No            0
+VALUE          Ascend-Route-IPX        Route-IPX-Yes           1
+VALUE          Ascend-Bridge           Bridge-No               0
+VALUE          Ascend-Bridge           Bridge-Yes              1
+VALUE                  Ascend-TS-Idle-Mode     TS-Idle-None            0
+VALUE          Ascend-TS-Idle-Mode     TS-Idle-Input           1
+VALUE                  Ascend-TS-Idle-Mode     TS-Idle-Input-Output    2
+VALUE          Ascend-Send-Auth        Send-Auth-None          0
+VALUE          Ascend-Send-Auth        Send-Auth-PAP           1
+VALUE          Ascend-Send-Auth        Send-Auth-CHAP          2
+VALUE          Ascend-Send-Auth        Send-Auth-MS-CHAP       3
+VALUE          Ascend-Link-Compression Link-Comp-None          0
+VALUE          Ascend-Link-Compression Link-Comp-Stac          1
+VALUE          Ascend-Link-Compression Link-Comp-Stac-Draft-9  2
+VALUE          Ascend-Link-Compression Link-Comp-MS-Stac       3
+VALUE          Ascend-History-Weigh-Type       History-Constant        0
+VALUE          Ascend-History-Weigh-Type       History-Linear          1
+VALUE          Ascend-History-Weigh-Type       History-Quadratic       2
+VALUE          Ascend-Callback         Callback-No             0
+VALUE          Ascend-Callback         Callback-Yes            1
+VALUE          Ascend-Expect-Callback  Expect-Callback-No      0
+VALUE          Ascend-Expect-Callback  Expect-Callback-Yes     1
+VALUE          Ascend-Data-Svc         Switched-Voice-Bearer   0
+VALUE          Ascend-Data-Svc         Switched-56KR           1
+VALUE          Ascend-Data-Svc         Switched-64K            2
+VALUE          Ascend-Data-Svc         Switched-64KR           3
+VALUE          Ascend-Data-Svc         Switched-56K            4
+VALUE          Ascend-Data-Svc         Switched-384KR          5
+VALUE          Ascend-Data-Svc         Switched-384K           6
+VALUE          Ascend-Data-Svc         Switched-1536K          7
+VALUE          Ascend-Data-Svc         Switched-1536KR         8
+VALUE          Ascend-Data-Svc         Switched-128K           9
+VALUE          Ascend-Data-Svc         Switched-192K           10
+VALUE          Ascend-Data-Svc         Switched-256K           11
+VALUE          Ascend-Data-Svc         Switched-320K           12
+VALUE          Ascend-Data-Svc         Switched-384K-MR        13
+VALUE          Ascend-Data-Svc         Switched-448K           14
+VALUE          Ascend-Data-Svc         Switched-512K           15
+VALUE          Ascend-Data-Svc         Switched-576K           16
+VALUE          Ascend-Data-Svc         Switched-640K           17
+VALUE          Ascend-Data-Svc         Switched-704K           18
+VALUE          Ascend-Data-Svc         Switched-768K           19
+VALUE          Ascend-Data-Svc         Switched-832K           20
+VALUE          Ascend-Data-Svc         Switched-896K           21
+VALUE          Ascend-Data-Svc         Switched-960K           22
+VALUE          Ascend-Data-Svc         Switched-1024K          23
+VALUE          Ascend-Data-Svc         Switched-1088K          24
+VALUE          Ascend-Data-Svc         Switched-1152K          25
+VALUE          Ascend-Data-Svc         Switched-1216K          26
+VALUE          Ascend-Data-Svc         Switched-1280K          27
+VALUE          Ascend-Data-Svc         Switched-1344K          28
+VALUE          Ascend-Data-Svc         Switched-1408K          29
+VALUE          Ascend-Data-Svc         Switched-1472K          30
+VALUE          Ascend-Data-Svc         Switched-1600K          31
+VALUE          Ascend-Data-Svc         Switched-1664K          32
+VALUE          Ascend-Data-Svc         Switched-1728K          33
+VALUE          Ascend-Data-Svc         Switched-1792K          34
+VALUE          Ascend-Data-Svc         Switched-1856K          35
+VALUE          Ascend-Data-Svc         Switched-1920K          36
+VALUE          Ascend-Data-Svc         Switched-inherited              37
+VALUE          Ascend-Data-Svc         Switched-restricted-bearer-x30  38
+VALUE          Ascend-Data-Svc         Switched-clear-bearer-v110      39
+VALUE          Ascend-Data-Svc         Switched-restricted-64-x30      40
+VALUE          Ascend-Data-Svc         Switched-clear-56-v110          41
+VALUE          Ascend-Data-Svc         Switched-modem                  42
+VALUE          Ascend-Data-Svc         Switched-atmodem                43
+VALUE          Ascend-Data-Svc         Nailed-56KR             1
+VALUE          Ascend-Data-Svc         Nailed-64K              2
+VALUE          Ascend-Force-56         Force-56-No             0
+VALUE          Ascend-Force-56         Force-56-Yes            1
+VALUE          Ascend-PW-Lifetime      Lifetime-In-Days        0
+VALUE          Ascend-PW-Warntime      Days-Of-Warning         0
+VALUE          Ascend-PPP-VJ-1172      PPP-VJ-1172             1
+VALUE          Ascend-PPP-VJ-Slot-Comp VJ-Slot-Comp-No         1
+VALUE          Ascend-Require-Auth     Not-Require-Auth        0
+VALUE          Ascend-Require-Auth     Require-Auth            1
+VALUE          Ascend-Token-Immediate  Tok-Imm-No              0
+VALUE          Ascend-Token-Immediate  Tok-Imm-Yes             1
+VALUE          Ascend-DBA-Monitor              DBA-Transmit            0
+VALUE          Ascend-DBA-Monitor      DBA-Transmit-Recv       1
+VALUE          Ascend-DBA-Monitor      DBA-None                2
+VALUE          Ascend-FR-Type          Ascend-FR-DTE           0
+VALUE          Ascend-FR-Type          Ascend-FR-DCE           1
+VALUE          Ascend-FR-Type          Ascend-FR-NNI           2
+VALUE          Ascend-FR-Link-Mgt      Ascend-FR-No-Link-Mgt   0
+VALUE          Ascend-FR-Link-Mgt      Ascend-FR-T1-617D       1
+VALUE          Ascend-FR-Link-Mgt      Ascend-FR-Q-933A        2
+VALUE          Ascend-FR-LinkUp        Ascend-LinkUp-Default   0
+VALUE          Ascend-FR-LinkUp        Ascend-LinkUp-AlwaysUp  1
+VALUE          Ascend-Multicast-Client Multicast-No            0
+VALUE          Ascend-Multicast-Client Multicast-Yes           1
+VALUE          Ascend-User-Acct-Type   Ascend-User-Acct-None   0
+VALUE          Ascend-User-Acct-Type   Ascend-User-Acct-User   1
+VALUE          Ascend-User-Acct-Type   Ascend-User-Acct-User-Default   2
+VALUE          Ascend-User-Acct-Base   Base-10                 0
+VALUE          Ascend-User-Acct-Base   Base-16                 1
+VALUE          Ascend-DHCP-Reply       DHCP-Reply-No           0
+VALUE          Ascend-DHCP-Reply       DHCP-Reply-Yes          1
+VALUE          Ascend-Client-Assign-DNS        DNS-Assign-No           0
+VALUE          Ascend-Client-Assign-DNS        DNS-Assign-Yes          1
+VALUE          Ascend-Event-Type       Ascend-ColdStart        1
+VALUE          Ascend-Event-Type       Ascend-Session-Event    2
+VALUE          Ascend-BACP-Enable      BACP-No                 0
+VALUE          Ascend-BACP-Enable      BACP-Yes                1
+VALUE          Ascend-Dialout-Allowed  Dialout-Not-Allowed     0
+VALUE          Ascend-Dialout-Allowed  Dialout-Allowed         1
+VALUE          Ascend-Shared-Profile-Enable    Shared-Profile-No       0
+VALUE          Ascend-Shared-Profile-Enable    Shared-Profile-Yes      1
+VALUE          Ascend-Temporary-Rtes   Temp-Rtes-No            0
+VALUE          Ascend-Temporary-Rtes   Temp-Rtes-Yes           1
diff --git a/raddb/dictionary.cisco b/raddb/dictionary.cisco
new file mode 100644 (file)
index 0000000..9e840f7
--- /dev/null
@@ -0,0 +1,71 @@
+#
+# dictionary.cisco
+#
+#              Accounting VSAs by
+#              "Marcelo M. Sosa Lugones" <marcelo@sosa.com.ar>
+#
+# Version:     @(#)dictionary.cisco  1.01  21-Mar-1999  miquels@cistron.nl
+#
+
+VENDOR         Cisco           9
+
+#
+#      Standard attribute
+#
+ATTRIBUTE      Cisco-AVPair    1       string          Cisco
+
+#
+#      Extra attributes sent by the Cisco, if you configure
+#      "radius-server vsa accounting" (requires IOS11.2+).
+#
+ATTRIBUTE       Cisco-Multilink-ID              187     integer                Cisco
+ATTRIBUTE       Cisco-Num-In-Multilink          188     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Input-Octets          190     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Output-Octets         191     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Input-Packets         192     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Output-Packets        193     integer                Cisco
+ATTRIBUTE       Cisco-Maximun-Time              194     integer                Cisco
+ATTRIBUTE       Cisco-Disconnect-Cause          195     integer                Cisco
+ATTRIBUTE       Cisco-Data-Rate                 197     integer                Cisco
+ATTRIBUTE       Cisco-PreSession-Time           198     integer                Cisco
+ATTRIBUTE       Cisco-PW-Lifetime               208     integer                Cisco
+ATTRIBUTE       Cisco-IP-Direct                 209     integer                Cisco
+ATTRIBUTE       Cisco-PPP-VJ-Slot-Comp          210     integer                Cisco
+ATTRIBUTE       Cisco-PPP-Async-Map             212     integer                Cisco
+ATTRIBUTE       Cisco-IP-Pool-Definition        217     integer                Cisco
+ATTRIBUTE       Cisco-Asing-IP-Pool             218     integer                Cisco
+ATTRIBUTE       Cisco-Route-IP                  228     integer                Cisco
+ATTRIBUTE       Cisco-Link-Compression          233     integer                Cisco
+ATTRIBUTE       Cisco-Target-Util               234     integer                Cisco
+ATTRIBUTE       Cisco-Maximun-Channels          235     integer                Cisco
+ATTRIBUTE       Cisco-Data-Filter               242     integer                Cisco
+ATTRIBUTE       Cisco-Call-Filter               243     integer                Cisco
+ATTRIBUTE       Cisco-Idle-Limit                244     integer                Cisco
+ATTRIBUTE       Cisco-Xmit-Rate                 255     integer                Cisco
+
+VALUE           Cisco-Disconnect-Cause        Unknown                 2
+VALUE           Cisco-Disconnect-Cause        CLID-Authentication-Failure     4
+VALUE           Cisco-Disconnect-Cause        No-Carrier              10
+VALUE           Cisco-Disconnect-Cause        Lost-Carrier            11
+VALUE           Cisco-Disconnect-Cause        No-Detected-Result-Codes        12
+VALUE           Cisco-Disconnect-Cause        User-Ends-Session       20
+VALUE           Cisco-Disconnect-Cause        Idle-Timeout            21
+VALUE           Cisco-Disconnect-Cause        Exit-Telnet-Session     22
+VALUE           Cisco-Disconnect-Cause        No-Remote-IP-Addr       23
+VALUE           Cisco-Disconnect-Cause        Exit-Raw-TCP            24
+VALUE           Cisco-Disconnect-Cause        Password-Fail           25
+VALUE           Cisco-Disconnect-Cause        Raw-TCP-Disabled        26
+VALUE           Cisco-Disconnect-Cause        Control-C-Detected      27
+VALUE           Cisco-Disconnect-Cause        EXEC-Program-Destroyed  28
+VALUE           Cisco-Disconnect-Cause        Timeout-PPP-LCP         40
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-LCP-Negotiation      41
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-PAP-Auth-Fail        42
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-CHAP-Auth    43
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-Remote-Auth  44
+VALUE           Cisco-Disconnect-Cause        PPP-Remote-Terminate    45
+VALUE           Cisco-Disconnect-Cause        PPP-Closed-Event        46
+VALUE           Cisco-Disconnect-Cause        Session-Timeout         100
+VALUE           Cisco-Disconnect-Cause        Session-Failed-Security 101
+VALUE           Cisco-Disconnect-Cause        Session-End-Callback    102
+VALUE           Cisco-Disconnect-Cause        Invalid-Protocol        120
+
diff --git a/raddb/dictionary.compat b/raddb/dictionary.compat
new file mode 100644 (file)
index 0000000..4ffc7a3
--- /dev/null
@@ -0,0 +1,48 @@
+#
+#      Obsolete names for backwards compatibility with older users files.
+#      Move the $INCLUDE in the main dictionary file to the end if you want
+#      these names to be used in the "details" logfile.
+#
+ATTRIBUTE      Client-Id               4       ipaddr
+ATTRIBUTE      Client-Port-Id          5       integer
+ATTRIBUTE      User-Service-Type       6       integer
+ATTRIBUTE      Framed-Address          8       ipaddr
+ATTRIBUTE      Framed-Netmask          9       ipaddr
+ATTRIBUTE      Framed-Filter-Id        11      string
+ATTRIBUTE      Login-Host              14      ipaddr
+ATTRIBUTE      Login-Port              16      integer
+ATTRIBUTE      Old-Password            17      string
+ATTRIBUTE      Port-Message            18      string
+ATTRIBUTE      Dialback-No             19      string
+ATTRIBUTE      Dialback-Name           20      string
+ATTRIBUTE      Challenge-State         24      string
+VALUE          Framed-Compression      Van-Jacobsen-TCP-IP     1
+VALUE          Framed-Compression      VJ-TCP-IP               1
+VALUE          Service-Type            Shell-User              6
+VALUE          Auth-Type               Unix                    1
+VALUE          Service-Type            Dialback-Login-User     3
+VALUE          Service-Type            Dialback-Framed-User    4
+
+#
+#      For compatibility with MERIT users files.
+#
+ATTRIBUTE      NAS-Port                5       integer
+ATTRIBUTE      Login-Host              14      ipaddr
+ATTRIBUTE      Login-Callback-Number   19      string
+ATTRIBUTE      Framed-Callback-Id      20      string
+ATTRIBUTE      Client-Port-DNIS        30      string
+ATTRIBUTE      Caller-ID               31      string
+VALUE          Service-Type            Login                   1
+VALUE          Service-Type            Framed                  2
+VALUE          Service-Type            Callback-Login          3
+VALUE          Service-Type            Callback-Framed         4
+VALUE          Service-Type            Exec-User               7
+
+#
+#      For compatibility with ESVA RADIUS, Old Cistron RADIUS
+#
+ATTRIBUTE      Session                 1034    integer
+ATTRIBUTE      User-Name-Is-Star       1035    integer
+VALUE          User-Name-Is-Star       No                      0
+VALUE          User-Name-Is-Star       Yes                     1
+VALUE          Auth-Type               None                    254
diff --git a/raddb/dictionary.livingston b/raddb/dictionary.livingston
new file mode 100644 (file)
index 0000000..495abb5
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Vendor-Specific attributes use the SMI Network Management Private
+# Enterprise Code from the "Assigned Numbers" RFC
+#
+VENDOR         Livingston      307
+
+#
+# Livingston Vendor-Specific Attributes (requires ComOS 3.8)
+#
+ATTRIBUTE      LE-Terminate-Detail     2       string  Livingston
+ATTRIBUTE      LE-Advice-of-Charge     3       string  Livingston
+
diff --git a/raddb/dictionary.shiva b/raddb/dictionary.shiva
new file mode 100644 (file)
index 0000000..b80ec6a
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# Shiva dictionary.
+#
+#              Shiva Inc.
+#              http://www.shiva.com/
+#
+#              Enable by putting the line "$INCLUDE dictionary.shiva" into
+#              the main dictionary file.
+#
+# Version:     1.00  27-Apr-1999  contributed by Alan DeKok
+#
+
+VENDOR Shiva           166
+
+#      Shiva Extensions
+
+#
+#      ??? I don't know what this is, but it's "Acct-Link-Count"
+#      in the main dictionary.
+#
+#ATTRIBUTE     Shiva-User-Attributes           51      string
+
+ATTRIBUTE      Shiva-Called-Number             90      string Shiva
+ATTRIBUTE      Shiva-Calling-Number            91      string Shiva
+ATTRIBUTE      Shiva-Customer-Id               92      string Shiva
+ATTRIBUTE      Shiva-Type-Of-Service           93      integer Shiva
+ATTRIBUTE      Shiva-Link-Speed                94      integer Shiva
+ATTRIBUTE      Shiva-Links-In-Bundle           95      integer Shiva
+ATTRIBUTE      Shiva-Compression-Type          96      integer Shiva
+ATTRIBUTE      Shiva-Link-Protocol             97      integer Shiva
+ATTRIBUTE      Shiva-Network-Protocols         98      integer Shiva
+ATTRIBUTE      Shiva-Session-Id                99      integer Shiva
+ATTRIBUTE      Shiva-Disconnect-Reason         100     integer Shiva
+ATTRIBUTE      Shiva-Acct-Serv-Switch          101     ipaddr Shiva
+ATTRIBUTE      Shiva-Event-Flags               102     integer Shiva
+ATTRIBUTE      Shiva-Function                  103     integer Shiva
+ATTRIBUTE      Shiva-Connect-Reason            104     integer Shiva
+
+#      Shiva Type Of Service Values
+
+VALUE  Shiva-Type-Of-Service   Analog                  1
+VALUE  Shiva-Type-Of-Service   Digitized-Analog        2
+VALUE  Shiva-Type-Of-Service   Digital                 3
+VALUE  Shiva-Type-Of-Service   Digital-V110            4
+VALUE  Shiva-Type-Of-Service   Digital-V120            5
+VALUE  Shiva-Type-Of-Service   Digital-Leased-Line     6
+
+#      Shiva Link Protocol Values
+
+VALUE  Shiva-Link-Protocol     HDLC                    1
+VALUE  Shiva-Link-Protocol     ARAV1                   2
+VALUE  Shiva-Link-Protocol     ARAV2                   3
+VALUE  Shiva-Link-Protocol     SHELL                   4
+VALUE  Shiva-Link-Protocol     AALAP                   5
+VALUE  Shiva-Link-Protocol     SLIP                    6
+
+#      Shiva Connect Reason Values
+
+VALUE  Shiva-Connect-Reason    Remote                  1
+VALUE  Shiva-Connect-Reason    Dialback                2
+VALUE  Shiva-Connect-Reason    Virtual-Connection      3
+VALUE  Shiva-Connect-Reason    Bandwidth-On-Demand     4
+
+#      Shiva Disconnect Reason Values
+
+VALUE  Shiva-Disconnect-Reason Remote                  1
+VALUE  Shiva-Disconnect-Reason Error                   2
+VALUE  Shiva-Disconnect-Reason Idle-Timeout            3
+VALUE  Shiva-Disconnect-Reason Session-Timeout         4
+VALUE  Shiva-Disconnect-Reason Admin-Disconnect        5
+VALUE  Shiva-Disconnect-Reason Dialback                6
+VALUE  Shiva-Disconnect-Reason Virtual-Connection      7
+VALUE  Shiva-Disconnect-Reason Bandwidth-On-Demand     8
+VALUE  Shiva-Disconnect-Reason Failed-Authentication   9
+VALUE  Shiva-Disconnect-Reason Preempted               10
+VALUE  Shiva-Disconnect-Reason Blocked                 11
+VALUE  Shiva-Disconnect-Reason Tariff-Management       12
+VALUE  Shiva-Disconnect-Reason Backup                  13
+
+#      Shiva Function Values
+
+VALUE  Shiva-Function          Unknown                 0
+VALUE  Shiva-Function          Dialin                  1
+VALUE  Shiva-Function          Dialout                 2
+VALUE  Shiva-Function          Lan-To-Lan              3
+
diff --git a/raddb/dictionary.tunnel b/raddb/dictionary.tunnel
new file mode 100644 (file)
index 0000000..01692a3
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# dictionary.tunnel
+#
+#              Experimental tunneling attributes.
+#
+#
+# Version:     @(#)dictionary.tunnel  1.10  11-Nov-1998  miquels@cistron.nl
+#
+
+#
+#      Tunneling Attributes
+#
+ATTRIBUTE      Tunnel-Type                     64      integer
+ATTRIBUTE      Tunnel-Medium-Type              65      integer
+ATTRIBUTE      Acct-Tunnel-Client-Endpoint     66      string
+ATTRIBUTE      Tunnel-Server-Endpoint          67      string
+ATTRIBUTE      Acct-Tunnel-Connection-Id       68      string
+ATTRIBUTE      Tunnel-Password                 69      string
+ATTRIBUTE      Private-Group-Id                75      integer
+
+VALUE          Framed-Protocol         PPTP                    9
+
+#  Some of the new Tunnel values 
+VALUE          Tunnel-Security         None                    0
+VALUE          Tunnel-Security         Control-Only            1
+VALUE          Tunnel-Security         Data-Only               2
+VALUE          Tunnel-Security         Both                    3
+
+#      Tunnel Type
+
+VALUE          Tunnel-Type     PPTP    1
+VALUE          Tunnel-Type     L2F     2
+VALUE          Tunnel-Type     L2TP    3
+VALUE          Tunnel-Type     ATMP    4
+VALUE          Tunnel-Type     VTP     5
+VALUE          Tunnel-Type     AH      6
+VALUE          Tunnel-Type     IP      7
+VALUE          Tunnel-Type     MIN-IP  8
+VALUE          Tunnel-Type     ESP     9
+VALUE          Tunnel-Type     GRE     10
+VALUE          Tunnel-Type     DVS     11
+#
+
+#      Tunnel Medium Type
+
+VALUE          Tunnel-Medium-Type      IP              1
+VALUE          Tunnel-Medium-Type      X25             2
+VALUE          Tunnel-Medium-Type      ATM             3
+VALUE          Tunnel-Medium-Type      Frame-Relay     4
+
diff --git a/raddb/dictionary.usr b/raddb/dictionary.usr
new file mode 100644 (file)
index 0000000..348044e
--- /dev/null
@@ -0,0 +1,876 @@
+#
+# dictionary.usr       USR Robotics dictionary.
+#
+#              Taken from the dictionary included with the USR RADIUS server,
+#              and adjusted a bit.
+#
+# Version:     @(#)dictionary.usr  1.10  11-Nov-1998  miquels@cistron.nl
+#
+
+#
+#      USR specific attributes
+#
+# Prompt value should be 1 for echo, 0 for no echo, default 1.
+#ATTRIBUTE     Prompt                  64      integer
+ATTRIBUTE      Multi-Link-Flag         126     integer
+ATTRIBUTE      Char-Noecho             250     integer
+
+#
+#      USR specific Integer Translations
+#
+
+VALUE          Termination-Action      Manage-Resources        2
+
+VALUE          Service-Type            Authenticate-User       8
+VALUE          Service-Type            Dialback-NAS-User       9
+
+VALUE          Acct-Status-Type        Modem-Start             4
+VALUE          Acct-Status-Type        Modem-Stop              5
+VALUE          Acct-Status-Type        Cancel                  6
+
+VALUE          Multi-Link-Flag         True                    1
+VALUE          Multi-Link-Flag         False                   0
+
+#      USR specific Authentication Types
+
+VALUE          Acct-Authentic          None                    0
+VALUE          Acct-Authentic          Remote                  3
+VALUE          Acct-Authentic          RADIUS                  4
+VALUE          Acct-Authentic          MNET                    5
+VALUE          Acct-Authentic          KCHAP                   6
+VALUE          Acct-Authentic          TACACS                  7
+VALUE          Acct-Authentic          Realm                   8
+VALUE          Acct-Authentic          Local                   9
+VALUE          Acct-Authentic          File                    10
+VALUE          Acct-Authentic          Local-VPN               11
+
+#
+#      USR Extensions: USR Vendor-Specific stuff.
+#
+#      For now in NMC format (whatever that stands for), though the
+#      normal vendor-specific format would work just as well.
+#
+#
+
+ATTRIB_NMC     USR-Last-Number-Dialed-Out              0x0066  string
+ATTRIB_NMC     USR-Last-Number-Dialed-In-DNIS          0x00E8  string
+ATTRIB_NMC     USR-Last-Callers-Number-ANI             0x00E9  string
+ATTRIB_NMC     USR-Channel                             0xBF38  integer 
+ATTRIB_NMC     USR-Event-Id                            0xBFBE  integer
+ATTRIB_NMC     USR-Event-Date-Time                     0xBF2F  date
+ATTRIB_NMC     USR-Call-Start-Date-Time                0xBFF7  date
+ATTRIB_NMC     USR-Call-End-Date-Time                  0xBFF6  date
+ATTRIB_NMC     USR-Default-DTE-Data-Rate               0x005E  integer
+ATTRIB_NMC     USR-Initial-Rx-Link-Data-Rate           0xBF2D  integer
+ATTRIB_NMC     USR-Final-Rx-Link-Data-Rate             0xBF2C  integer
+ATTRIB_NMC     USR-Initial-Tx-Link-Data-Rate           0x006A  integer
+ATTRIB_NMC     USR-Final-Tx-Link-Data-Rate             0x006B  integer
+ATTRIB_NMC     USR-Chassis-Temperature                 0xBF31  integer
+ATTRIB_NMC     USR-Chassis-Temp-Threshold              0xBE84  integer
+ATTRIB_NMC     USR-Actual-Voltage                      0xBF32  integer
+ATTRIB_NMC     USR-Expected-Voltage                    0xBF33  integer
+ATTRIB_NMC     USR-Power-Supply-Number                 0xBF34  integer
+ATTRIB_NMC     USR-Card-Type                           0xBE85  integer
+ATTRIB_NMC     USR-Chassis-Slot                        0xBF39  integer
+ATTRIB_NMC     USR-Sync-Async-Mode                     0x0067  integer
+ATTRIB_NMC     USR-Originate-Answer-Mode               0x0068  integer
+ATTRIB_NMC     USR-Modulation-Type                     0x006C  integer
+ATTRIB_NMC     USR-Connect-Term-Reason                 0x009B  integer
+ATTRIB_NMC     USR-Failure-to-Connect-Reason           0x0069  integer
+ATTRIB_NMC     USR-Equalization-Type                   0x006F  integer
+ATTRIB_NMC     USR-Fallback-Enabled                    0x0070  integer
+ATTRIB_NMC     USR-Connect-Time-Limit                  0xBFE7  integer
+ATTRIB_NMC     USR-Number-of-Rings-Limit               0xBFE6  integer
+ATTRIB_NMC     USR-DTE-Data-Idle-Timout                0x0048  integer
+ATTRIB_NMC     USR-Characters-Sent                     0x0071  integer
+ATTRIB_NMC     USR-Characters-Received                 0x0072  integer
+ATTRIB_NMC     USR-Blocks-Sent                         0x0075  integer
+ATTRIB_NMC     USR-Blocks-Received                     0x0076  integer
+ATTRIB_NMC     USR-Blocks-Resent                       0x0077  integer
+ATTRIB_NMC     USR-Retrains-Requested                  0x0078  integer
+ATTRIB_NMC     USR-Retrains-Granted                    0x0079  integer
+ATTRIB_NMC     USR-Line-Reversals                      0x007A  integer
+ATTRIB_NMC     USR-Number-Of-Characters-Lost           0x007B  integer
+ATTRIB_NMC     USR-Number-of-Blers                     0x007D  integer
+ATTRIB_NMC     USR-Number-of-Link-Timeouts             0x007E  integer
+ATTRIB_NMC     USR-Number-of-Fallbacks                 0x007F  integer
+ATTRIB_NMC     USR-Number-of-Upshifts                  0x0080  integer
+ATTRIB_NMC     USR-Number-of-Link-NAKs                 0x0081  integer
+ATTRIB_NMC     USR-DTR-False-Timeout                   0x00BE  integer
+ATTRIB_NMC     USR-Fallback-Limit                      0x00BF  integer
+ATTRIB_NMC     USR-Block-Error-Count-Limit             0x00C0  integer
+ATTRIB_NMC     USR-DTR-True-Timeout                    0x00DA  integer
+ATTRIB_NMC     USR-Security-Login-Limit                0xBEDE  integer
+ATTRIB_NMC     USR-Security-Resp-Limit                 0xBEFA  integer
+ATTRIB_NMC     USR-DTE-Ring-No-Answer-Limit            0xBF17  integer
+ATTRIB_NMC     USR-Back-Channel-Data-Rate              0x007C  integer
+ATTRIB_NMC     USR-Simplified-MNP-Levels               0x0099  integer
+ATTRIB_NMC     USR-Simplified-V42bis-Usage             0x00C7  integer
+ATTRIB_NMC     USR-Mbi_Ct_PRI_Card_Slot                0x0184  integer
+ATTRIB_NMC     USR-Mbi_Ct_TDM_Time_Slot                0x0185  integer
+ATTRIB_NMC     USR-Mbi_Ct_PRI_Card_Span_Line           0x0186  integer
+ATTRIB_NMC     USR-Mbi_Ct_BChannel_Used                0x0187  integer
+ATTRIB_NMC     USR-Physical-State                      0xBE77  integer
+ATTRIB_NMC     USR-Packet-Bus-Session                  0xBF14  integer
+ATTRIB_NMC     USR-Server-Time                         0xF000  date
+
+# 0xBE5D-0xBE63 sent with Event-Id 79
+ATTRIB_NMC     USR-Channel-Connected-To                0xBE5D  integer
+ATTRIB_NMC     USR-Slot-Connected-To                   0xBE5E  integer 
+ATTRIB_NMC     USR-Device-Connected-To                 0xBE5F  integer
+ATTRIB_NMC     USR-NFAS-ID                             0xBE60  integer
+ATTRIB_NMC     USR-Q931-Call-Reference-Value           0xBE61  integer
+ATTRIB_NMC     USR-Call-Event-Code                     0xBE62  integer
+ATTRIB_NMC     USR-DS0                                 0xBE63  integer
+# DS0s sent with Event-Id 77,78
+ATTRIB_NMC     USR-DS0s                                0xBE64  string
+# Gateway-IP-Address sent with Event-Id 71,72
+ATTRIB_NMC     USR-Gateway-IP-Address                  0xBE66  ipaddr
+
+
+#
+# These are CCA Radius attributes
+#
+ATTRIB_NMC     USR-PW_USR_IFilter_IP                   0x9000  string
+ATTRIB_NMC     USR-PW_USR_IFilter_IPX                  0x9001  string
+ATTRIB_NMC     USR-PW_USR_OFilter_IP                   0x9003  string
+ATTRIB_NMC     USR-PW_USR_OFilter_IPX                  0x9004  string
+ATTRIB_NMC     USR-PW_USR_OFilter_SAP                  0x9005  string
+ATTRIB_NMC     USR-PW_VPN_ID                           0x9006  string
+ATTRIB_NMC     USR-PW_VPN_Name                         0x9007  string
+ATTRIB_NMC     USR-PW_VPN_Neighbor                     0x9008  string
+ATTRIB_NMC     USR-PW_Framed_Routing_V2                0x9009  string
+ATTRIB_NMC     USR-PW_VPN_Gateway                      0x900a  string
+ATTRIB_NMC     USR-PW_Tunnel_Authentication            0x900b  string
+ATTRIB_NMC     USR-PW_Index                            0x900c  string
+ATTRIB_NMC     USR-PW_Cutoff                           0x900d  string
+ATTRIB_NMC     USR-PW_Packet                           0x900e  string
+ATTRIB_NMC     USR-Primary_DNS_Server                  0x900f  ipaddr
+ATTRIB_NMC     USR-Secondary_DNS_Server                0x9010  ipaddr
+ATTRIB_NMC     USR-Primary_NBNS_Server                 0x9011  ipaddr
+ATTRIB_NMC     USR-Secondary_NBNS_Server               0x9012  ipaddr
+ATTRIB_NMC     USR-Syslog-Tap                          0x9013  integer
+ATTRIB_NMC     USR-Chassis-Call-Slot                   0x9019  integer
+ATTRIB_NMC     USR-Chassis-Call-Span                   0x901A  integer
+ATTRIB_NMC     USR-Chassis-Call-Channel                0x901B  integer
+ATTRIB_NMC     USR-Keypress-Timeout                    0x901C  integer
+ATTRIB_NMC     USR-Unauthenticated-Time                0x901D  integer
+ATTRIB_NMC     USR-Connect-Speed                       0x9023  integer
+ATTRIB_NMC     USR-Framed_IP_Address_Pool_Name         0x9024  string
+ATTRIB_NMC     USR-MP-EDO                              0x9025  string  
+
+#
+# Pilgrim attributes
+# 
+ATTRIB_NMC     USR-Bearer-Capabilities                 0x9800  integer
+ATTRIB_NMC     USR-Speed-Of-Connection                 0x9801  integer
+ATTRIB_NMC     USR-Max-Channels                        0x9802  integer
+ATTRIB_NMC     USR-Channel-Expansion                   0x9803  integer
+ATTRIB_NMC     USR-Channel-Decrement                   0x9804  integer
+ATTRIB_NMC     USR-Expansion-Algorithm                 0x9805  integer
+ATTRIB_NMC     USR-Compression-Algorithm               0x9806  integer
+ATTRIB_NMC     USR-Receive-Acc-Map                     0x9807  integer
+ATTRIB_NMC     USR-Transmit-Acc-Map                    0x9808  integer
+ATTRIB_NMC     USR-Compression-Reset-Mode              0x980a  integer
+ATTRIB_NMC     USR-Min-Compression-Size                0x980b  integer
+ATTRIB_NMC     USR-IP                                  0x980c  integer
+ATTRIB_NMC     USR-IPX                                 0x980d  integer
+ATTRIB_NMC     USR-Filter-Zones                        0x980e  integer
+ATTRIB_NMC     USR-Appletalk                           0x980f  integer
+ATTRIB_NMC     USR-Bridging                            0x9810  integer
+ATTRIB_NMC     USR-Spoofing                            0x9811  integer
+ATTRIB_NMC     USR-Host-Type                           0x9812  integer
+ATTRIB_NMC     USR-Send-Name                           0x9813  string
+ATTRIB_NMC     USR-Send-Password                       0x9814  string
+ATTRIB_NMC     USR-Start-Time                          0x9815  integer
+ATTRIB_NMC     USR-End-Time                            0x9816  integer
+ATTRIB_NMC     USR-Send-Script1                        0x9817  string
+ATTRIB_NMC     USR-Reply-Script1                       0x9818  string
+ATTRIB_NMC     USR-Send-Script2                        0x9819  string
+ATTRIB_NMC     USR-Reply-Script2                       0x981a  string
+ATTRIB_NMC     USR-Send-Script3                        0x981b  string
+ATTRIB_NMC     USR-Reply-Script3                       0x981c  string
+ATTRIB_NMC     USR-Send-Script4                        0x981d  string
+ATTRIB_NMC     USR-Reply-Script4                       0x981e  string
+ATTRIB_NMC     USR-Send-Script5                        0x981f  string
+ATTRIB_NMC     USR-Reply-Script5                       0x9820  string
+ATTRIB_NMC     USR-Send-Script6                        0x9821  string
+ATTRIB_NMC     USR-Reply-Script6                       0x9822  string
+ATTRIB_NMC     USR-Terminal-Type                       0x9823  string
+ATTRIB_NMC     USR-Appletalk-Network-Range             0x9824  integer
+ATTRIB_NMC     USR-Local-IP-Address                    0x9825  string
+ATTRIB_NMC     USR-Routing-Protocol                    0x9826  integer
+ATTRIB_NMC     USR-Modem-Group                         0x9827  integer
+ATTRIB_NMC     USR-Modem-Training-Time                 0x9842  integer
+ATTRIB_NMC     USR-Interface-Index                     0x9843  integer
+ATTRIB_NMC     USR-MP-MRRU                             0x982f  integer
+
+#      Virtual Private Network Extensions
+#
+ATTRIB_NMC     USR-VPN-ID                      36870       integer
+ATTRIB_NMC     USR-VPN-Name                    36871       string
+ATTRIB_NMC     USR-VPN-Neighbor                36872       ipaddr
+ATTRIB_NMC     USR-RIPV2                       36873       integer
+ATTRIB_NMC     USR-VPN-Gateway                 36874       string
+ATTRIB_NMC     USR-VPN-Auth-Vector             36875       string
+ATTRIB_NMC     USR-RQ_INDEX                    36876       integer
+#USR_ATTRIBUTE     User-Cutoff                 36877      integer
+ATTRIB_NMC     USR-PACKET                      36878       string
+ATTRIB_NMC     USR-IP-Filter-In                36864       string
+ATTRIB_NMC     USR-IPX-Filter-In               36865       string
+ATTRIB_NMC     USR-SAP-Filter-In               36866       string
+ATTRIB_NMC     USR-IP-Filter-Out               36867       string
+ATTRIB_NMC     USR-IPX-Filter-Out              36868       string
+ATTRIB_NMC     USR-SAP-Filter-Out              36869       string
+ATTRIB_NMC     USR-Syslog-Tap                  36883       integer
+ATTRIB_NMC     USR-MIC                         36884       string
+ATTRIB_NMC     USR-Log-Filter-Packets          36887       string
+ATTRIB_NMC     USR-Chassis-Call-Slot           36889       integer
+ATTRIB_NMC     USR-Chassis-Call-Span           36890       integer
+ATTRIB_NMC     USR-Chassis-Call-Channel        36891       integer
+ATTRIB_NMC     USR-Keypress-Timeout            36892       integer
+ATTRIB_NMC     USR-Unauthenticated-Time        36893       integer
+ATTRIB_NMC     USR-VPN-Encrypter               36894       integer
+ATTRIB_NMC     USR-Re-Chap-Timeout             36896       integer
+ATTRIB_NMC     USR-Tunnel-Switch-Endpoint      39016       string
+
+# End of VPN crap
+
+#
+#      Integer Translations
+#
+
+#VALUE         USR-Character-Echo      Echo-On                 0
+#VALUE         USR-Character-Echo      Echo-Off                1
+
+VALUE          USR-RIPV2               Off                     0
+VALUE          USR-RIPV2               On                      1
+
+VALUE          USR-Syslog-Tap          Off                     0
+VALUE          USR-Syslog-Tap          On-Raw                  1
+VALUE          USR-Syslog-Tap          On-Framed               2
+VALUE          USR-Syslog-Tap          Unknown        4294967295
+
+
+#      Event Indentifiers
+
+VALUE  USR-Event-Id    Module-Inserted                 6
+VALUE  USR-Event-Id    Module-Removed                  7
+VALUE  USR-Event-Id    PSU-Voltage-Alarm               8
+VALUE  USR-Event-Id    PSU-Failed                      9
+VALUE  USR-Event-Id    HUB-Temp-Out-of-Range           10
+VALUE  USR-Event-Id    Fan-Failed                      11
+VALUE  USR-Event-Id    Watchdog-Timeout                12
+VALUE  USR-Event-Id    Mgmt-Bus-Failure                13
+VALUE  USR-Event-Id    In-Connection-Est               14
+VALUE  USR-Event-Id    Out-Connection-Est              15
+VALUE  USR-Event-Id    In-Connection-Term              16
+VALUE  USR-Event-Id    Out-Connection-Term             17
+VALUE  USR-Event-Id    Connection-Failed               18
+VALUE  USR-Event-Id    Connection-Timeout              19
+VALUE  USR-Event-Id    DTE-Transmit-Idle               20
+VALUE  USR-Event-Id    DTR-True                        21
+VALUE  USR-Event-Id    DTR-False                       22
+VALUE  USR-Event-Id    Block-Error-at-Threshold        23
+VALUE  USR-Event-Id    Fallbacks-at-Threshold          24
+VALUE  USR-Event-Id    No-Dial-Tone-Detected           25
+VALUE  USR-Event-Id    No-Loop-Current-Detected        26
+VALUE  USR-Event-Id    Yellow-Alarm                    27
+VALUE  USR-Event-Id    Red-Alarm                       28
+VALUE  USR-Event-Id    Loss-Of-Signal                  29
+VALUE  USR-Event-Id    Rcv-Alrm-Ind-Signal             30
+VALUE  USR-Event-Id    Timing-Source-Switch            31
+VALUE  USR-Event-Id    Modem-Reset-by-DTE              32
+VALUE  USR-Event-Id    Modem-Ring-No-Answer            33
+VALUE  USR-Event-Id    DTE-Ring-No-Answer              34
+VALUE  USR-Event-Id    Pkt-Bus-Session-Active          35
+VALUE  USR-Event-Id    Pkt-Bus-Session-Congestion      36
+VALUE  USR-Event-Id    Pkt-Bus-Session-Lost            37
+VALUE  USR-Event-Id    Pkt-Bus-Session-Inactive        38
+VALUE  USR-Event-Id    User-Interface-Reset            39
+VALUE  USR-Event-Id    Gateway-Port-Out-of-Service     40
+VALUE  USR-Event-Id    Gateway-Port-Link-Active        41
+VALUE  USR-Event-Id    Dial-Out-Login-Failure          42
+VALUE  USR-Event-Id    Dial-In-Login-Failure           43
+VALUE  USR-Event-Id    Dial-Out-Restricted-Number      44
+VALUE  USR-Event-Id    Dial-Back-Restricted-Number     45
+VALUE  USR-Event-Id    User-Blacklisted                46
+VALUE  USR-Event-Id    Attempted-Login-Blacklisted     47
+VALUE  USR-Event-Id    Response-Attempt-Limit-Exceeded 48
+VALUE  USR-Event-Id    Login-Attempt-Limit-Exceeded    49
+VALUE  USR-Event-Id    Dial-Out-Call-Duration          50
+VALUE  USR-Event-Id    Dial-In-Call-Duration           51
+VALUE  USR-Event-Id    Pkt-Bus-Session-Err-Status      52
+VALUE  USR-Event-Id    NMC-AutoRespnse-Trap            53
+VALUE  USR-Event-Id    Acct-Server-Contact-Loss        54
+VALUE  USR-Event-Id    Yellow-Alarm-Clear              55
+VALUE  USR-Event-Id    Red-Alarm-Clear                 56
+VALUE  USR-Event-Id    Loss-Of-Signal-Clear            57
+VALUE  USR-Event-Id    Rcv-Alrm-Ind-Signal-Clear       58
+VALUE  USR-Event-Id    Incoming-Connection-Established 59
+VALUE  USR-Event-Id    Outgoing-Connection-Established 60
+VALUE  USR-Event-Id    Incoming-Connection-Terminated  61
+VALUE  USR-Event-Id    Outgoing-Connection-Terminated  62
+VALUE  USR-Event-Id    Connection-Attempt-Failure      63
+VALUE  USR-Event-Id    Continuous-CRC-Alarm            64
+VALUE  USR-Event-Id    Continuous-CRC-Alarm-Clear      65
+VALUE  USR-Event-Id    Physical-State-Change           66
+VALUE  USR-Event-Id    Gateway-Network-Failed          71
+VALUE  USR-Event-Id    Gateway-Network-Restored        72
+VALUE  USR-Event-Id    Packet-Bus-Clock-Lost           73
+VALUE  USR-Event-Id    Packet-Bus-Clock-Restored       74
+VALUE  USR-Event-Id    D-Channel-In-Service            75
+VALUE  USR-Event-Id    D-Channel-Out-of-Service        76
+VALUE  USR-Event-Id    DS0s-In-Service                 77
+VALUE  USR-Event-Id    DS0s-Out-of-Service             78
+VALUE  USR-Event-Id    T1/T1PRI/E1PRI-Call-Event       79
+VALUE  USR-Event-Id    Psu-Incompatible                80
+
+
+VALUE  USR-Card-Type   SlotEmpty                       1
+VALUE  USR-Card-Type   SlotUnknown                     2
+VALUE  USR-Card-Type   NetwMgtCard                     3
+VALUE  USR-Card-Type   DualT1NAC                       4
+VALUE  USR-Card-Type   DualModemNAC                    5
+VALUE  USR-Card-Type   QuadModemNAC                    6
+VALUE  USR-Card-Type   TrGatewayNAC                    7
+VALUE  USR-Card-Type   X25GatewayNAC                   8
+VALUE  USR-Card-Type   DualV34ModemNAC                 9
+VALUE  USR-Card-Type   QuadV32DigitalModemNAC          10
+VALUE  USR-Card-Type   QuadV32AnalogModemNAC           11
+VALUE  USR-Card-Type   QuadV32DigAnlModemNAC           12
+VALUE  USR-Card-Type   QuadV34DigModemNAC              13
+VALUE  USR-Card-Type   QuadV34AnlModemNAC              14
+VALUE  USR-Card-Type   QuadV34DigAnlModemNAC           15
+VALUE  USR-Card-Type   SingleT1NAC                     16
+VALUE  USR-Card-Type   EthernetGatewayNAC              17
+VALUE  USR-Card-Type   AccessServer                    18
+VALUE  USR-Card-Type   486TrGatewayNAC                 19
+VALUE  USR-Card-Type   486EthernetGatewayNAC           20
+VALUE  USR-Card-Type   DualRS232NAC                    22
+VALUE  USR-Card-Type   486X25GatewayNAC                23
+VALUE  USR-Card-Type   ApplicationServerNAC            25
+VALUE  USR-Card-Type   ISDNGatewayNAC                  26
+VALUE  USR-Card-Type   ISDNpriT1NAC                    27
+VALUE  USR-Card-Type   ClkedNetMgtCard                 28
+VALUE  USR-Card-Type   ModemPoolManagementNAC          29
+VALUE  USR-Card-Type   ModemPoolNetserverNAC           30
+VALUE  USR-Card-Type   ModemPoolV34ModemNAC            31
+VALUE  USR-Card-Type   ModemPoolISDNNAC                32
+VALUE  USR-Card-Type   NTServerNAC                     33
+VALUE  USR-Card-Type   QuadV34DigitalG2NAC             34
+VALUE  USR-Card-Type   QuadV34AnalogG2NAC              35
+VALUE  USR-Card-Type   QuadV34DigAnlgG2NAC             36
+VALUE  USR-Card-Type   NETServerFrameRelayNAC          37
+VALUE  USR-Card-Type   NETServerTokenRingNAC           38
+VALUE  USR-Card-Type   X2524ChannelNAC                 39
+VALUE  USR-Card-Type   WirelessGatewayNac              42
+
+VALUE  USR-Card-Type   EnhancedAccessServer              44
+VALUE  USR-Card-Type   EnhancedISDNGatewayNAC            45
+
+VALUE  USR-Card-Type   DualT1NIC                       1001
+VALUE  USR-Card-Type   DualAlogMdmNIC                  1002
+VALUE  USR-Card-Type   QuadDgtlMdmNIC                  1003
+VALUE  USR-Card-Type   QuadAlogDgtlMdmNIC              1004
+VALUE  USR-Card-Type   TokenRingNIC                    1005
+VALUE  USR-Card-Type   SingleT1NIC                     1006
+VALUE  USR-Card-Type   EthernetNIC                     1007
+VALUE  USR-Card-Type   ShortHaulDualT1NIC              1008
+VALUE  USR-Card-Type   DualAlogMgdIntlMdmNIC           1009
+VALUE  USR-Card-Type   X25NIC                          1010
+VALUE  USR-Card-Type   QuadAlogNonMgdMdmNIC            1011
+VALUE  USR-Card-Type   QuadAlogMgdIntlMdmNIC           1012
+VALUE  USR-Card-Type   QuadAlogNonMgdIntlMdmNIC        1013
+VALUE  USR-Card-Type   QuadLsdLiMgdMdmNIC              1014
+VALUE  USR-Card-Type   QuadLsdLiNonMgdMdmNIC           1015
+VALUE  USR-Card-Type   QuadLsdLiMgdIntlMdmNIC          1016
+VALUE  USR-Card-Type   QuadLsdLiNonMgdIntlMdmNIC       1017
+VALUE  USR-Card-Type   HSEthernetWithV35NIC            1018
+VALUE  USR-Card-Type   HSEthernetWithoutV35NIC         1019
+VALUE  USR-Card-Type   DualHighSpeedV35NIC             1020
+VALUE  USR-Card-Type   QuadV35RS232LowSpeedNIC         1021
+VALUE  USR-Card-Type   DualE1NIC                       1022
+VALUE  USR-Card-Type   ShortHaulDualE1NIC              1023
+VALUE  USR-Card-Type   BellcoreLongHaulDualT1NIC       1025
+VALUE  USR-Card-Type   BellcoreShrtHaulDualT1NIC       1026
+VALUE  USR-Card-Type   SCSIEdgeServerNIC               1027
+
+
+VALUE  USR-Default-DTE-Data-Rate             110-BPS         1
+VALUE  USR-Default-DTE-Data-Rate             300-BPS         2
+VALUE  USR-Default-DTE-Data-Rate             600-BPS         3
+VALUE  USR-Default-DTE-Data-Rate             1200-BPS        4
+VALUE  USR-Default-DTE-Data-Rate             2400-BPS        5
+VALUE  USR-Default-DTE-Data-Rate             4800-BPS        6
+VALUE  USR-Default-DTE-Data-Rate             7200-BPS        7
+VALUE  USR-Default-DTE-Data-Rate             9600-BPS        8
+VALUE  USR-Default-DTE-Data-Rate             12K-BPS         9
+VALUE  USR-Default-DTE-Data-Rate             14.4K-BPS       10
+VALUE  USR-Default-DTE-Data-Rate             16.8-BPS        11
+VALUE  USR-Default-DTE-Data-Rate             19.2K-BPS       12
+VALUE  USR-Default-DTE-Data-Rate             38.4K-BPS       13
+VALUE  USR-Default-DTE-Data-Rate             75-BPS          14
+VALUE  USR-Default-DTE-Data-Rate             450-BPS         15
+VALUE  USR-Default-DTE-Data-Rate             UNKNOWN-BPS     16
+VALUE  USR-Default-DTE-Data-Rate             57.6K-BPS       17
+VALUE  USR-Default-DTE-Data-Rate             21.6K-BPS       18
+VALUE  USR-Default-DTE-Data-Rate             24K-BPS         19
+VALUE  USR-Default-DTE-Data-Rate             26K-BPS         20
+VALUE  USR-Default-DTE-Data-Rate             28K-BPS         21
+VALUE  USR-Default-DTE-Data-Rate             115K-BPS        22
+
+
+VALUE  USR-Initial-Rx-Link-Data-Rate   110-BPS         1
+VALUE  USR-Initial-Rx-Link-Data-Rate   300-BPS         2
+VALUE  USR-Initial-Rx-Link-Data-Rate   600-BPS         3
+VALUE  USR-Initial-Rx-Link-Data-Rate   1200-BPS        4
+VALUE  USR-Initial-Rx-Link-Data-Rate   2400-XBPS       5
+VALUE  USR-Initial-Rx-Link-Data-Rate   4800-BPS        6
+VALUE  USR-Initial-Rx-Link-Data-Rate   7200-BPS        7
+VALUE  USR-Initial-Rx-Link-Data-Rate   9600-BPS        8
+VALUE  USR-Initial-Rx-Link-Data-Rate   12K-BPS         9
+VALUE  USR-Initial-Rx-Link-Data-Rate   14.4K-BPS       10
+VALUE  USR-Initial-Rx-Link-Data-Rate   16.8-BPS        11
+VALUE  USR-Initial-Rx-Link-Data-Rate   19.2K-BPS       12
+VALUE  USR-Initial-Rx-Link-Data-Rate   38.4K-BPS       13
+VALUE  USR-Initial-Rx-Link-Data-Rate   75-BPS          14
+VALUE  USR-Initial-Rx-Link-Data-Rate   450-BPS         15
+VALUE  USR-Initial-Rx-Link-Data-Rate   UNKNOWN-BPS     16
+VALUE  USR-Initial-Rx-Link-Data-Rate   57.6K-BPS       17
+VALUE  USR-Initial-Rx-Link-Data-Rate   21.6K-BPS       18
+VALUE  USR-Initial-Rx-Link-Data-Rate   24K-BPS         19
+VALUE  USR-Initial-Rx-Link-Data-Rate   26K-BPS         20
+VALUE  USR-Initial-Rx-Link-Data-Rate   28K-BPS         21
+VALUE  USR-Initial-Rx-Link-Data-Rate   115K-BPS        22
+VALUE  USR-Initial-Rx-Link-Data-Rate   31K-BPS         23
+VALUE  USR-Initial-Rx-Link-Data-Rate   33K-BPS         24
+VALUE  USR-Initial-Rx-Link-Data-Rate   32K-BPS         25
+VALUE  USR-Initial-Rx-Link-Data-Rate   36K-BPS         26
+VALUE  USR-Initial-Rx-Link-Data-Rate   40K-BPS         27
+VALUE  USR-Initial-Rx-Link-Data-Rate   44K-BPS         28
+VALUE  USR-Initial-Rx-Link-Data-Rate   48K-BPS         29
+VALUE  USR-Initial-Rx-Link-Data-Rate   49333-BPS       30
+VALUE  USR-Initial-Rx-Link-Data-Rate   50666-BPS       31
+VALUE  USR-Initial-Rx-Link-Data-Rate   52K-BPS         32
+VALUE  USR-Initial-Rx-Link-Data-Rate   53333-BPS       33
+VALUE  USR-Initial-Rx-Link-Data-Rate   54666-BPS       34
+VALUE  USR-Initial-Rx-Link-Data-Rate   56K-BPS         35
+VALUE  USR-Initial-Rx-Link-Data-Rate   57333-BPS       36
+VALUE  USR-Initial-Rx-Link-Data-Rate   58666-BPS       37
+VALUE  USR-Initial-Rx-Link-Data-Rate   60K-BPS         38
+VALUE  USR-Initial-Rx-Link-Data-Rate   61333-BPS       39
+VALUE  USR-Initial-Rx-Link-Data-Rate   64K-BPS         40
+
+
+VALUE  USR-Final-Rx-Link-Data-Rate             110-BPS         1
+VALUE  USR-Final-Rx-Link-Data-Rate             300-BPS         2
+VALUE  USR-Final-Rx-Link-Data-Rate             600-BPS         3
+VALUE  USR-Final-Rx-Link-Data-Rate             1200-BPS        4
+VALUE  USR-Final-Rx-Link-Data-Rate             2400-BPS        5
+VALUE  USR-Final-Rx-Link-Data-Rate             4800-BPS        6
+VALUE  USR-Final-Rx-Link-Data-Rate             7200-BPS        7
+VALUE  USR-Final-Rx-Link-Data-Rate             9600-BPS        8
+VALUE  USR-Final-Rx-Link-Data-Rate             12K-BPS         9
+VALUE  USR-Final-Rx-Link-Data-Rate             14.4K-BPS       10
+VALUE  USR-Final-Rx-Link-Data-Rate             16.8-BPS        11
+VALUE  USR-Final-Rx-Link-Data-Rate             19.2K-BPS       12
+VALUE  USR-Final-Rx-Link-Data-Rate             38.4K-BPS       13
+VALUE  USR-Final-Rx-Link-Data-Rate             75-BPS          14
+VALUE  USR-Final-Rx-Link-Data-Rate             450-BPS         15
+VALUE  USR-Final-Rx-Link-Data-Rate             UNKNOWN-BPS     16
+VALUE  USR-Final-Rx-Link-Data-Rate             57.6K-BPS       17
+VALUE  USR-Final-Rx-Link-Data-Rate             21.6K-BPS       18
+VALUE  USR-Final-Rx-Link-Data-Rate             24K-BPS         19
+VALUE  USR-Final-Rx-Link-Data-Rate             26K-BPS         20
+VALUE  USR-Final-Rx-Link-Data-Rate             28K-BPS         21
+VALUE  USR-Final-Rx-Link-Data-Rate             115K-BPS        22
+VALUE  USR-Final-Rx-Link-Data-Rate             31K-BPS         23
+VALUE  USR-Final-Rx-Link-Data-Rate             33K-BPS         24
+VALUE  USR-Final-Rx-Link-Data-Rate             32K-BPS         25
+VALUE  USR-Final-Rx-Link-Data-Rate             36K-BPS         26
+VALUE  USR-Final-Rx-Link-Data-Rate             40K-BPS         27
+VALUE  USR-Final-Rx-Link-Data-Rate             44K-BPS         28
+VALUE  USR-Final-Rx-Link-Data-Rate             48K-BPS         29
+VALUE  USR-Final-Rx-Link-Data-Rate             49333-BPS       30
+VALUE  USR-Final-Rx-Link-Data-Rate             50666-BPS       31
+VALUE  USR-Final-Rx-Link-Data-Rate             52K-BPS         32
+VALUE  USR-Final-Rx-Link-Data-Rate             53333-BPS       33
+VALUE  USR-Final-Rx-Link-Data-Rate             54666-BPS       34
+VALUE  USR-Final-Rx-Link-Data-Rate             56K-BPS         35
+VALUE  USR-Final-Rx-Link-Data-Rate             57333-BPS       36
+VALUE  USR-Final-Rx-Link-Data-Rate             58666-BPS       37
+VALUE  USR-Final-Rx-Link-Data-Rate             60K-BPS         38
+VALUE  USR-Final-Rx-Link-Data-Rate             61333-BPS       39
+VALUE  USR-Final-Rx-Link-Data-Rate             64K-BPS         40
+
+
+VALUE  USR-Initial-Tx-Link-Data-Rate   110-BPS         1
+VALUE  USR-Initial-Tx-Link-Data-Rate   300-BPS         2
+VALUE  USR-Initial-Tx-Link-Data-Rate   600-BPS         3
+VALUE  USR-Initial-Tx-Link-Data-Rate   1200-BPS        4
+VALUE  USR-Initial-Tx-Link-Data-Rate   2400-BPS        5
+VALUE  USR-Initial-Tx-Link-Data-Rate   4800-BPS        6
+VALUE  USR-Initial-Tx-Link-Data-Rate   7200-BPS        7
+VALUE  USR-Initial-Tx-Link-Data-Rate   9600-BPS        8
+VALUE  USR-Initial-Tx-Link-Data-Rate   12K-BPS         9
+VALUE  USR-Initial-Tx-Link-Data-Rate   14.4K-BPS       10
+VALUE  USR-Initial-Tx-Link-Data-Rate   16.8-BPS        11
+VALUE  USR-Initial-Tx-Link-Data-Rate   19.2K-BPS       12
+VALUE  USR-Initial-Tx-Link-Data-Rate   38.4K-BPS       13
+VALUE  USR-Initial-Tx-Link-Data-Rate   75-BPS          14
+VALUE  USR-Initial-Tx-Link-Data-Rate   450-BPS         15
+VALUE  USR-Initial-Tx-Link-Data-Rate   UNKNOWN-BPS     16
+VALUE  USR-Initial-Tx-Link-Data-Rate   57.6K-BPS       17
+VALUE  USR-Initial-Tx-Link-Data-Rate   21.6K-BPS       18
+VALUE  USR-Initial-Tx-Link-Data-Rate   24K-BPS         19
+VALUE  USR-Initial-Tx-Link-Data-Rate   26K-BPS         20
+VALUE  USR-Initial-Tx-Link-Data-Rate   28K-BPS         21
+VALUE  USR-Initial-Tx-Link-Data-Rate   115K-BPS        22
+VALUE  USR-Initial-Tx-Link-Data-Rate   31K-BPS         23      
+VALUE  USR-Initial-Tx-Link-Data-Rate   33K-BPS         24
+VALUE  USR-Initial-Tx-Link-Data-Rate   32K-BPS         25
+VALUE  USR-Initial-Tx-Link-Data-Rate   36K-BPS         26
+VALUE  USR-Initial-Tx-Link-Data-Rate   40K-BPS         27
+VALUE  USR-Initial-Tx-Link-Data-Rate   44K-BPS         28
+VALUE  USR-Initial-Tx-Link-Data-Rate   48K-BPS         29
+VALUE  USR-Initial-Tx-Link-Data-Rate   49333-BPS       30
+VALUE  USR-Initial-Tx-Link-Data-Rate   50666-BPS       31
+VALUE  USR-Initial-Tx-Link-Data-Rate   52K-BPS         32
+VALUE  USR-Initial-Tx-Link-Data-Rate   53333-BPS       33
+VALUE  USR-Initial-Tx-Link-Data-Rate   54666-BPS       34
+VALUE  USR-Initial-Tx-Link-Data-Rate   56K-BPS         35
+VALUE  USR-Initial-Tx-Link-Data-Rate   57333-BPS       36
+VALUE  USR-Initial-Tx-Link-Data-Rate   58666-BPS       37
+VALUE  USR-Initial-Tx-Link-Data-Rate   60K-BPS         38
+VALUE  USR-Initial-Tx-Link-Data-Rate   61333-BPS       39
+VALUE  USR-Initial-Tx-Link-Data-Rate   64K-BPS         40
+
+
+VALUE  USR-Final-Tx-Link-Data-Rate             110-BPS         1
+VALUE  USR-Final-Tx-Link-Data-Rate             300-BPS         2
+VALUE  USR-Final-Tx-Link-Data-Rate             600-BPS         3
+VALUE  USR-Final-Tx-Link-Data-Rate             1200-BPS        4
+VALUE  USR-Final-Tx-Link-Data-Rate             2400-BPS        5
+VALUE  USR-Final-Tx-Link-Data-Rate             4800-BPS        6
+VALUE  USR-Final-Tx-Link-Data-Rate             7200-BPS        7
+VALUE  USR-Final-Tx-Link-Data-Rate             9600-BPS        8
+VALUE  USR-Final-Tx-Link-Data-Rate             12K-BPS         9
+VALUE  USR-Final-Tx-Link-Data-Rate             14.4K-BPS       10
+VALUE  USR-Final-Tx-Link-Data-Rate             16.8-BPS        11
+VALUE  USR-Final-Tx-Link-Data-Rate             19.2K-BPS       12
+VALUE  USR-Final-Tx-Link-Data-Rate             38.4K-BPS       13
+VALUE  USR-Final-Tx-Link-Data-Rate             75-BPS          14
+VALUE  USR-Final-Tx-Link-Data-Rate             450-BPS         15
+VALUE  USR-Final-Tx-Link-Data-Rate             UNKNOWN-BPS     16
+VALUE  USR-Final-Tx-Link-Data-Rate             57.6K-BPS       17
+VALUE  USR-Final-Tx-Link-Data-Rate             21.6K-BPS       18
+VALUE  USR-Final-Tx-Link-Data-Rate             24K-BPS         19
+VALUE  USR-Final-Tx-Link-Data-Rate             26K-BPS         20
+VALUE  USR-Final-Tx-Link-Data-Rate             28K-BPS         21
+VALUE  USR-Final-Tx-Link-Data-Rate             115K-BPS        22
+VALUE  USR-Final-Tx-Link-Data-Rate             31K-BPS         23
+VALUE  USR-Final-Tx-Link-Data-Rate             33K-BPS         24
+VALUE  USR-Final-Tx-Link-Data-Rate             32K-BPS         25
+VALUE  USR-Final-Tx-Link-Data-Rate             36K-BPS         26
+VALUE  USR-Final-Tx-Link-Data-Rate             40K-BPS         27
+VALUE  USR-Final-Tx-Link-Data-Rate             44K-BPS         28
+VALUE  USR-Final-Tx-Link-Data-Rate             48K-BPS         29
+VALUE  USR-Final-Tx-Link-Data-Rate             49333-BPS       30
+VALUE  USR-Final-Tx-Link-Data-Rate             50666-BPS       31
+VALUE  USR-Final-Tx-Link-Data-Rate             52K-BPS         32
+VALUE  USR-Final-Tx-Link-Data-Rate             53333-BPS       33
+VALUE  USR-Final-Tx-Link-Data-Rate             54666-BPS       34
+VALUE  USR-Final-Tx-Link-Data-Rate             56K-BPS         35
+VALUE  USR-Final-Tx-Link-Data-Rate             57333-BPS       36
+VALUE  USR-Final-Tx-Link-Data-Rate             58666-BPS       37
+VALUE  USR-Final-Tx-Link-Data-Rate             60K-BPS         38
+VALUE  USR-Final-Tx-Link-Data-Rate             61333-BPS       39
+VALUE  USR-Final-Tx-Link-Data-Rate             64K-BPS         40
+
+# Value Connect Speed  /* Added by Krish */
+
+VALUE  USR-Connect-Speed  NONE     0 
+VALUE  USR-Connect-Speed  300_BPS          1 
+VALUE  USR-Connect-Speed  1200_BPS          2 
+VALUE  USR-Connect-Speed  2400_BPS          3 
+VALUE  USR-Connect-Speed  4800_BPS          4 
+VALUE  USR-Connect-Speed  7200_BPS          5 
+VALUE  USR-Connect-Speed  9600_BPS          6 
+VALUE  USR-Connect-Speed  12000_BPS      7 
+VALUE  USR-Connect-Speed  14400_BPS      8 
+VALUE  USR-Connect-Speed  16800_BPS      9
+VALUE  USR-Connect-Speed  19200_BPS     10 
+VALUE  USR-Connect-Speed  21600_BPS     11 
+VALUE  USR-Connect-Speed  28800_BPS     12 
+VALUE  USR-Connect-Speed  38400_BPS     13 
+VALUE  USR-Connect-Speed  57600_BPS     14 
+VALUE  USR-Connect-Speed  44000_BPS     27 
+VALUE  USR-Connect-Speed  45333_BPS     28 
+VALUE  USR-Connect-Speed  46666_BPS     29 
+VALUE  USR-Connect-Speed  48000_BPS     30 
+VALUE  USR-Connect-Speed  49333_BPS     31 
+VALUE  USR-Connect-Speed  50666_BPS     32 
+VALUE  USR-Connect-Speed  52000_BPS     33 
+VALUE  USR-Connect-Speed  53333_BPS     34 
+VALUE  USR-Connect-Speed  54666_BPS     35 
+VALUE  USR-Connect-Speed  56000_BPS     36 
+VALUE  USR-Connect-Speed  57333_BPS     37 
+VALUE  USR-Connect-Speed  64000_BPS     38 
+VALUE  USR-Connect-Speed  25333_BPS     39 
+VALUE  USR-Connect-Speed  26666_BPS      40
+VALUE  USR-Connect-Speed  28000_BPS      41 
+VALUE  USR-Connect-Speed  115200_BPS     15 
+VALUE  USR-Connect-Speed  288000_BPS      16
+VALUE  USR-Connect-Speed  75_1200_BPS    17 
+VALUE  USR-Connect-Speed  1200_75_BPS    18
+VALUE  USR-Connect-Speed  24000_BPS      19
+VALUE  USR-Connect-Speed  26400_BPS      20
+VALUE  USR-Connect-Speed  31200_BPS      21
+VALUE  USR-Connect-Speed  33600_BPS      22
+VALUE  USR-Connect-Speed  33333_BPS      23
+VALUE  USR-Connect-Speed  37333_BPS      24
+VALUE  USR-Connect-Speed  41333_BPS      25
+VALUE  USR-Connect-Speed  42666_BPS      26
+VALUE  USR-Connect-Speed  29333_BPS      42 
+VALUE  USR-Connect-Speed  30666_BPS      43
+VALUE  USR-Connect-Speed  32000_BPS      44 
+VALUE  USR-Connect-Speed  34666_BPS      45 
+VALUE  USR-Connect-Speed  36000_BPS      46 
+VALUE  USR-Connect-Speed  38666_BPS      47 
+VALUE  USR-Connect-Speed  40000_BPS      48 
+VALUE  USR-Connect-Speed  58666_BPS      49 
+VALUE  USR-Connect-Speed  60000_BPS      50 
+VALUE  USR-Connect-Speed  61333_BPS      51 
+VALUE  USR-Connect-Speed  62666_BPS      52 
+
+# End of Connect-Speed / * Added by Krish */
+
+#
+
+VALUE  USR-Sync-Async-Mode             Asynchronous                    1
+VALUE  USR-Sync-Async-Mode             Synchronous                     2
+
+VALUE  USR-Originate-Answer-Mode       Originate_in_Originate_Mode     1
+VALUE  USR-Originate-Answer-Mode       Originate_in_Answer_Mode        2
+VALUE  USR-Originate-Answer-Mode       Answer_in_Originate_Mode        3
+VALUE  USR-Originate-Answer-Mode       Answer_in_Answer_Mode           4
+
+VALUE  USR-Modulation-Type             usRoboticsHST                   1
+VALUE  USR-Modulation-Type             ccittV32                        2
+VALUE  USR-Modulation-Type             ccittV22bis                     3
+VALUE  USR-Modulation-Type             bell103                         4
+VALUE  USR-Modulation-Type             ccittV21                        5
+VALUE  USR-Modulation-Type             bell212                         6
+VALUE  USR-Modulation-Type             ccittV32bis                     7
+VALUE  USR-Modulation-Type             ccittV23                        8
+VALUE  USR-Modulation-Type             negotiationFailed               9
+VALUE  USR-Modulation-Type             bell208b                        10
+VALUE  USR-Modulation-Type             v21FaxClass1                    11
+VALUE  USR-Modulation-Type             v27FaxClass1                    12
+VALUE  USR-Modulation-Type             v29FaxClass1                    13
+VALUE  USR-Modulation-Type             v17FaxClass1                    14
+VALUE  USR-Modulation-Type             v21FaxClass2                    15
+VALUE  USR-Modulation-Type             v27FaxClass2                    16
+VALUE  USR-Modulation-Type             v29FaxClass2                    17
+VALUE  USR-Modulation-Type             v17FaxClass2                    18
+VALUE  USR-Modulation-Type             v32Terbo                        19
+VALUE  USR-Modulation-Type             v34                             20
+VALUE  USR-Modulation-Type             vFC                             21
+VALUE  USR-Modulation-Type             v34plus                         22
+
+VALUE  USR-Connect-Term-Reason dtrDrop                         1
+VALUE  USR-Connect-Term-Reason escapeSequence                  2
+VALUE  USR-Connect-Term-Reason athCommand                      3
+VALUE  USR-Connect-Term-Reason carrierLoss                     4
+VALUE  USR-Connect-Term-Reason inactivityTimout                5
+VALUE  USR-Connect-Term-Reason mnpIncompatible                 6
+VALUE  USR-Connect-Term-Reason undefined                       7
+VALUE  USR-Connect-Term-Reason remotePassword                  8
+VALUE  USR-Connect-Term-Reason linkPassword                    9
+VALUE  USR-Connect-Term-Reason retransmitLimit                 10
+VALUE  USR-Connect-Term-Reason linkDisconnectMsgReceived       11
+VALUE  USR-Connect-Term-Reason noLoopCurrent                   12
+VALUE  USR-Connect-Term-Reason invalidSpeed                    13
+VALUE  USR-Connect-Term-Reason unableToRetrain                 14
+VALUE  USR-Connect-Term-Reason managementCommand               15
+VALUE  USR-Connect-Term-Reason noDialTone                      16
+VALUE  USR-Connect-Term-Reason keyAbort                        17
+VALUE  USR-Connect-Term-Reason lineBusy                        18
+VALUE  USR-Connect-Term-Reason noAnswer                        19
+VALUE  USR-Connect-Term-Reason voice                           20
+VALUE  USR-Connect-Term-Reason noAnswerTone                    21
+VALUE  USR-Connect-Term-Reason noCarrier                       22
+VALUE  USR-Connect-Term-Reason undetermined                    23
+VALUE  USR-Connect-Term-Reason v42SabmeTimeout                 24
+VALUE  USR-Connect-Term-Reason v42BreakTimeout                 25
+VALUE  USR-Connect-Term-Reason v42DisconnectCmd                26
+VALUE  USR-Connect-Term-Reason v42IdExchangeFail               27
+VALUE  USR-Connect-Term-Reason v42BadSetup                     28
+VALUE  USR-Connect-Term-Reason v42InvalidCodeWord              29
+VALUE  USR-Connect-Term-Reason v42StringToLong                 30
+VALUE  USR-Connect-Term-Reason v42InvalidCommand               31
+VALUE  USR-Connect-Term-Reason none                            32      
+VALUE  USR-Connect-Term-Reason v32Cleardown                    33
+VALUE  USR-Connect-Term-Reason dialSecurity                    34
+VALUE  USR-Connect-Term-Reason remoteAccessDenied              35
+VALUE  USR-Connect-Term-Reason loopLoss                        36
+VALUE  USR-Connect-Term-Reason ds0Teardown                     37
+VALUE  USR-Connect-Term-Reason promptNotEnabled                38
+VALUE  USR-Connect-Term-Reason noPromptingInSync               39
+VALUE  USR-Connect-Term-Reason nonArqMode                      40
+VALUE  USR-Connect-Term-Reason modeIncompatible                41
+VALUE  USR-Connect-Term-Reason noPromptInNonARQ                42
+VALUE  USR-Connect-Term-Reason dialBackLink                    43
+VALUE  USR-Connect-Term-Reason linkAbort                       44
+VALUE  USR-Connect-Term-Reason autopassFailed                  45
+VALUE  USR-Connect-Term-Reason pbGenericError                  46
+VALUE  USR-Connect-Term-Reason pbLinkErrTxPreAck               47
+VALUE  USR-Connect-Term-Reason pbLinkErrTxTardyACK             48
+VALUE  USR-Connect-Term-Reason pbTransmitBusTimeout            49
+VALUE  USR-Connect-Term-Reason pbReceiveBusTimeout             50
+VALUE  USR-Connect-Term-Reason pbLinkErrTxTAL                  51
+VALUE  USR-Connect-Term-Reason pbLinkErrRxTAL                  52
+VALUE  USR-Connect-Term-Reason pbTransmitMasterTimeout         53
+VALUE  USR-Connect-Term-Reason pbClockMissing                  54
+VALUE  USR-Connect-Term-Reason pbReceivedLsWhileLinkUp         55
+VALUE  USR-Connect-Term-Reason pbOutOfSequenceFrame            56
+VALUE  USR-Connect-Term-Reason pbBadFrame                      57
+VALUE  USR-Connect-Term-Reason pbAckWaitTimeout                58
+VALUE  USR-Connect-Term-Reason pbReceivedAckSeqErr             59
+VALUE  USR-Connect-Term-Reason pbReceiveOvrflwRNRFail          60
+VALUE  USR-Connect-Term-Reason pbReceiveMsgBufOvrflw           61
+VALUE  USR-Connect-Term-Reason rcvdGatewayDiscCmd              62
+VALUE  USR-Connect-Term-Reason tokenPassingTimeout             63
+VALUE  USR-Connect-Term-Reason dspInterruptTimeout             64
+VALUE  USR-Connect-Term-Reason mnpProtocolViolation            65
+VALUE  USR-Connect-Term-Reason class2FaxHangupCmd              66
+VALUE  USR-Connect-Term-Reason hstSpeedSwitchTimeout           67
+
+VALUE  USR-Failure-to-Connect-Reason   dtrDrop                 1
+VALUE  USR-Failure-to-Connect-Reason   escapeSequence          2
+VALUE  USR-Failure-to-Connect-Reason   athCommand              3
+VALUE  USR-Failure-to-Connect-Reason   carrierLoss             4
+VALUE  USR-Failure-to-Connect-Reason   inactivityTimout        5
+VALUE  USR-Failure-to-Connect-Reason   mnpIncompatible         6
+VALUE  USR-Failure-to-Connect-Reason   undefined               7
+VALUE  USR-Failure-to-Connect-Reason   remotePassword          8
+VALUE  USR-Failure-to-Connect-Reason   linkPassword            9
+VALUE  USR-Failure-to-Connect-Reason   retransmitLimit         10
+VALUE  USR-Failure-to-Connect-Reason   linkDisconnectMsgRec    11
+VALUE  USR-Failure-to-Connect-Reason   noLoopCurrent           12
+VALUE  USR-Failure-to-Connect-Reason   invalidSpeed            13
+VALUE  USR-Failure-to-Connect-Reason   unableToRetrain         14
+VALUE  USR-Failure-to-Connect-Reason   managementCommand       15
+VALUE  USR-Failure-to-Connect-Reason   noDialTone              16
+VALUE  USR-Failure-to-Connect-Reason   keyAbort                17
+VALUE  USR-Failure-to-Connect-Reason   lineBusy                18
+VALUE  USR-Failure-to-Connect-Reason   noAnswer                19
+VALUE  USR-Failure-to-Connect-Reason   voice                   20
+VALUE  USR-Failure-to-Connect-Reason   noAnswerTone            21
+VALUE  USR-Failure-to-Connect-Reason   noCarrier               22
+VALUE  USR-Failure-to-Connect-Reason   undetermined            23
+VALUE  USR-Failure-to-Connect-Reason   v42SabmeTimeout         24
+VALUE  USR-Failure-to-Connect-Reason   v42BreakTimeout         25
+VALUE  USR-Failure-to-Connect-Reason   v42DisconnectCmd        26
+VALUE  USR-Failure-to-Connect-Reason   v42IdExchangeFail       27
+VALUE  USR-Failure-to-Connect-Reason   v42BadSetup             28
+VALUE  USR-Failure-to-Connect-Reason   v42InvalidCodeWord      29
+VALUE  USR-Failure-to-Connect-Reason   v42StringToLong         30
+VALUE  USR-Failure-to-Connect-Reason   v42InvalidCommand       31
+VALUE  USR-Failure-to-Connect-Reason   none                    32      
+VALUE  USR-Failure-to-Connect-Reason   v32Cleardown            33
+VALUE  USR-Failure-to-Connect-Reason   dialSecurity            34
+VALUE  USR-Failure-to-Connect-Reason   remoteAccessDenied      35
+VALUE  USR-Failure-to-Connect-Reason   loopLoss                36
+VALUE  USR-Failure-to-Connect-Reason   ds0Teardown             37
+VALUE  USR-Failure-to-Connect-Reason   promptNotEnabled        38
+VALUE  USR-Failure-to-Connect-Reason   noPromptingInSync       39
+VALUE  USR-Failure-to-Connect-Reason   nonArqMode              40
+VALUE  USR-Failure-to-Connect-Reason   modeIncompatible        41
+VALUE  USR-Failure-to-Connect-Reason   noPromptInNonARQ        42
+VALUE  USR-Failure-to-Connect-Reason   dialBackLink            43
+VALUE  USR-Failure-to-Connect-Reason   linkAbort               44
+VALUE  USR-Failure-to-Connect-Reason   autopassFailed          45
+VALUE  USR-Failure-to-Connect-Reason   pbGenericError          46
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrTxPreAck       47
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrTxTardyACK     48
+VALUE  USR-Failure-to-Connect-Reason   pbTransmitBusTimeout    49
+VALUE  USR-Failure-to-Connect-Reason   pbReceiveBusTimeout     50
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrTxTAL          51
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrRxTAL          52
+VALUE  USR-Failure-to-Connect-Reason   pbTransmitMasterTimeout 53
+VALUE  USR-Failure-to-Connect-Reason   pbClockMissing          54
+VALUE  USR-Failure-to-Connect-Reason   pbReceivedLsWhileLinkUp 55
+VALUE  USR-Failure-to-Connect-Reason   pbOutOfSequenceFrame    56
+VALUE  USR-Failure-to-Connect-Reason   pbBadFrame              57
+VALUE  USR-Failure-to-Connect-Reason   pbAckWaitTimeout        58
+VALUE  USR-Failure-to-Connect-Reason   pbReceivedAckSeqErr     59
+VALUE  USR-Failure-to-Connect-Reason   pbReceiveOvrflwRNRFail  60
+VALUE  USR-Failure-to-Connect-Reason   pbReceiveMsgBufOvrflw   61
+VALUE  USR-Failure-to-Connect-Reason   rcvdGatewayDiscCmd      62
+VALUE  USR-Failure-to-Connect-Reason   tokenPassingTimeout     63
+VALUE  USR-Failure-to-Connect-Reason   dspInterruptTimeout     64
+VALUE  USR-Failure-to-Connect-Reason   mnpProtocolViolation    65
+VALUE  USR-Failure-to-Connect-Reason   class2FaxHangupCmd      66
+VALUE  USR-Failure-to-Connect-Reason   hstSpeedSwitchTimeout   67
+
+VALUE  USR-Simplified-MNP-Levels               none                    1
+VALUE  USR-Simplified-MNP-Levels               mnpLevel3               2
+VALUE  USR-Simplified-MNP-Levels               mnpLevel4               3
+VALUE  USR-Simplified-MNP-Levels               ccittV42                4
+VALUE  USR-Simplified-MNP-Levels               usRoboticsHST           5
+VALUE  USR-Simplified-MNP-Levels               synchronousNone         6
+VALUE  USR-Simplified-MNP-Levels               mnpLevel2               7
+VALUE  USR-Simplified-MNP-Levels               mnp10                   8
+VALUE  USR-Simplified-MNP-Levels               v42Etc                  9
+
+VALUE  USR-Simplified-V42bis-Usage             none                    1
+VALUE  USR-Simplified-V42bis-Usage             ccittV42bis             2
+VALUE  USR-Simplified-V42bis-Usage             mnpLevel5               3
+
+VALUE  USR-Equalization-Type           Long            1
+VALUE  USR-Equalization-Type           Short           2
+
+
+VALUE  USR-Fallback-Enabled            Disabled        1
+VALUE  USR-Fallback-Enabled            Enabled         2
+
+
+VALUE  USR-Back-Channel-Data-Rate              450BPS          1
+VALUE  USR-Back-Channel-Data-Rate              300BPS          2
+VALUE  USR-Back-Channel-Data-Rate              None            3
+
+VALUE  USR-Device-Connected-To         None            1
+VALUE  USR-Device-Connected-To         isdnGateway     2
+VALUE  USR-Device-Connected-To         quadModem       3
+
+VALUE  USR-Call-Event-Code                     notSupported          1
+VALUE  USR-Call-Event-Code                     setup                 2
+VALUE  USR-Call-Event-Code                     usrSetup              3
+VALUE  USR-Call-Event-Code                     telcoDisconnect       4
+VALUE  USR-Call-Event-Code                     usrDisconnect         5
+VALUE  USR-Call-Event-Code                     noFreeModem           6
+VALUE  USR-Call-Event-Code                     modemsNotAllowed      7
+VALUE  USR-Call-Event-Code                     modemsRejectCall      8
+VALUE  USR-Call-Event-Code                     modemSetupTimeout     9
+VALUE  USR-Call-Event-Code                     noFreeIGW             10
+VALUE  USR-Call-Event-Code                     igwRejectCall         11
+VALUE  USR-Call-Event-Code                     igwSetupTimeout       12
+VALUE  USR-Call-Event-Code                     noFreeTdmts           13
+VALUE  USR-Call-Event-Code                     bcReject              14
+VALUE  USR-Call-Event-Code                     ieReject              15
+VALUE  USR-Call-Event-Code                     chidReject            16
+VALUE  USR-Call-Event-Code                     progReject            17
+VALUE  USR-Call-Event-Code                     callingPartyReject    18
+VALUE  USR-Call-Event-Code                     calledPartyReject     19
+VALUE  USR-Call-Event-Code                     blocked               20
+VALUE  USR-Call-Event-Code                     analogBlocked         21
+VALUE  USR-Call-Event-Code                     digitalBlocked        22
+VALUE  USR-Call-Event-Code                     outOfService          23
+VALUE  USR-Call-Event-Code                     busy                  24
+VALUE  USR-Call-Event-Code                     congestion            25
+VALUE  USR-Call-Event-Code                     protocolError         26 
+VALUE  USR-Call-Event-Code                     noFreeBchannel        27
+VALUE  USR-Call-Event-Code                     inOutCallCollision    28
+
diff --git a/raddb/dictionary.versanet b/raddb/dictionary.versanet
new file mode 100644 (file)
index 0000000..cd6a091
--- /dev/null
@@ -0,0 +1,50 @@
+#\r
+# dictionary.versanet Vendor specfic attributes for versanet\r
+#\r
+#\r
+#    VersaNet Communications, Inc.\r
+#     Http://www.versa-net.com\r
+#\r
+#\r
+#Versanet add Vendor specific terminal cause in our radius group.\r
+#You can follow this to set it in NAS box.\r
+#\r
+#          >> gr radius\r
+#          >> sh\r
+#          >> set 34 23\r
+#          >> co\r
+#\r
+#This will let our unit transfer every detail terminal cause \r
+#information to Redius server's accounting log file and  \r
+#save as "Vendor Specific=Terminate Cause". \r
+#\r
+# Version:   @(#)dictionary.versanet 1.00 22-Jul-1999 support@versanetcomm.com\r
+#\r
+\r
+VENDOR Versanet 2180\r
+\r
+ATTRIBUTE Versanet-Termination-Cause 1 integer Versanet\r
+\r
+VALUE Versanet-Termination-Cause Normal-Hangup-No-Error-Occurred 0\r
+VALUE Versanet-Termination-Cause Call-Waiting-Caused-Disconnect  3\r
+VALUE Versanet-Termination-Cause Physical-Carrier-Loss           4\r
+VALUE Versanet-Termination-Cause No-err-correction-at-other-end  5\r
+VALUE Versanet-Termination-Cause No-resp-to-feature-negotiation  6\r
+VALUE Versanet-Termination-Cause 1st-modem-async-only-2nd-sync   7\r
+VALUE Versanet-Termination-Cause No-framing-technique-in-common  8\r
+VALUE Versanet-Termination-Cause No-protocol-in-common           9\r
+VALUE Versanet-Termination-Cause Bad-resp-to-feature-negotiation 10\r
+VALUE Versanet-Termination-Cause No-sync-info-from-remote-modem  11\r
+VALUE Versanet-Termination-Cause Normal-Hangup-by-Remote-modem   12\r
+VALUE Versanet-Termination-Cause Retransmission-limit-reached    13\r
+VALUE Versanet-Termination-Cause Protocol-violation-occurred     14\r
+VALUE Versanet-Termination-Cause Lost-DTR                        15\r
+VALUE Versanet-Termination-Cause Received-GSTN-cleardown         16\r
+VALUE Versanet-Termination-Cause Inactivity-timeout              17\r
+VALUE Versanet-Termination-Cause Speed-not-supported             18\r
+VALUE Versanet-Termination-Cause Long-space-disconnect           19\r
+VALUE Versanet-Termination-Cause Key-abort-disconnect            20\r
+VALUE Versanet-Termination-Cause Clears-previous-disc-reason     21\r
+VALUE Versanet-Termination-Cause No-connection-established       22\r
+VALUE Versanet-Termination-Cause Disconnect-after-three-retrains 23\r
+\r
diff --git a/raddb/hints b/raddb/hints
new file mode 100644 (file)
index 0000000..9f7e1e8
--- /dev/null
@@ -0,0 +1,62 @@
+#
+# hints                The hints file. Matching can take place with the
+#              the Prefix and Suffix attributes, just like in
+#              the "users" file, but ONLY on the username.
+#
+#              Note that the name-value pairs that are set for each
+#              entry are _NOT_ passed back to the terminal server.
+#              Instead they are added to the information that has
+#              been _SENT_ by the terminal server.
+#
+#              This extra information can be used in the users file to
+#              match on. Usually this is done in the DEFAULT entries,
+#              of which there can be more than one.
+#
+#              In addition a matching entry can transform a username
+#              for authentication purposes if the "Strip-User-Name"
+#              variable is set to Yes in an entry (default is Yes).
+#
+#              A special non-protocol name-value pair called "Hint"
+#              can be set to match on in the "users" file.
+#
+#              The following is how most ISPs want to setup this stuff.
+#
+# Version:     @(#)  hints  1.10  20-Jun-1997  miquels@cistron.nl
+#
+
+
+DEFAULT        Prefix = "U", Strip-User-Name = No
+       Hint = "UUCP"
+
+DEFAULT        Prefix = "P", Strip-User-Name = Yes
+       Hint = "PPP",
+       Service-Type = Framed-User,
+       Framed-Protocol = PPP
+
+DEFAULT        Prefix = "S", Strip-User-Name = Yes
+       Hint = "SLIP",
+       Service-Type = Framed-User,
+       Framed-Protocol = SLIP
+
+DEFAULT        Prefix = "C", Strip-User-Name = Yes
+       Hint = "CSLIP",
+       Service-Type = Framed-User,
+       Framed-Protocol = SLIP,
+       Framed-Compression = Van-Jacobson-TCP-IP
+
+DEFAULT        Suffix = ".ppp", Strip-User-Name = Yes
+       Hint = "PPP",
+       Service-Type = Framed-User,
+       Framed-Protocol = PPP
+
+DEFAULT        Suffix = ".slip", Strip-User-Name = Yes
+       Hint = "SLIP",
+       Service-Type = Framed-User,
+       Framed-Protocol = SLIP
+
+DEFAULT        Suffix = ".cslip", Strip-User-Name = Yes
+       Hint = "CSLIP",
+       Service-Type = Framed-User,
+       Framed-Protocol = SLIP,
+       Framed-Compression = Van-Jacobson-TCP-IP
+
diff --git a/raddb/huntgroups b/raddb/huntgroups
new file mode 100644 (file)
index 0000000..f4fa5c2
--- /dev/null
@@ -0,0 +1,46 @@
+#
+# huntgroups   This file defines the `huntgroups' that you have. A
+#              huntgroup is defined by specifying the IP address of
+#              the NAS and possibly a port range. Port can be identified
+#              as just one port, or a range (from-to), and multiple ports
+#              or ranges of ports must be seperated by a comma. For
+#              example: 1,2,3-8
+#
+#              Matching is done while RADIUS scans the user file; if it
+#              includes the selection criterium "Huntgroup-Name = XXX"
+#              the huntgroup is looked up in this file to see if it
+#              matches. There can be multiple definitions of the same
+#              huntgroup; the first one that matches will be used.
+#
+#              This file can also be used to define restricted access
+#              to certain huntgroups. The second and following lines
+#              define the access restrictions (based on username and
+#              UNIX usergroup) for the huntgroup.
+#
+
+#
+# Our POP in Alphen a/d Rijn has 3 terminal servers. Create a Huntgroup-Name
+# called Alphen that matches on all three terminal servers.
+#
+#alphen                NAS-IP-Address = 192.168.2.5
+#alphen                NAS-IP-Address = 192.168.2.6
+#alphen                NAS-IP-Address = 192.168.2.7
+
+#
+# The POP in Delft consists of only one terminal server.
+#
+#delft         NAS-IP-Address = 192.168.3.5
+
+#
+# Ports 0-7 on the first terminal server in Alphen are connected to
+# a huntgroup that is for business users only. Note that only one
+# of the username or groupname has to match to get access (OR/OR).
+#
+# Note that this huntgroup is a subset of the "alphen" huntgroup.
+#
+#business      NAS-IP-Address = 192.168.2.5, NAS-Port-Id = 0-7
+#              User-Name = rogerl,
+#              User-Name = henks,
+#              Group = business,
+#              Group = staff
+
diff --git a/raddb/modules b/raddb/modules
new file mode 100644 (file)
index 0000000..d42ef52
--- /dev/null
@@ -0,0 +1,1416 @@
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  Create a unique accounting session Id.  Many NASes re-use
+#  or repeat values for Acct-Session-Id, causing no end of
+#  confusion.
+#
+#  This module will add a (probably) unique session id 
+#  to an accounting packet based on the attributes listed
+#  below found in the packet.  See doc/rlm_acct_unique for
+#  more information.
+#
+acct_unique {
+       key = "User-Name, Acct-Session-Id, NAS-IP-Address, Client-IP-Address, NAS-Port"
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+# The "always" module is here for debugging purposes. Each
+# instance simply returns the same result, always, without
+# doing anything.
+always fail {
+       rcode = fail
+}
+always reject {
+       rcode = reject
+}
+always noop {
+       rcode = noop
+}
+always handled {
+       rcode = handled
+}
+always updated {
+       rcode = updated
+}
+always notfound {
+       rcode = notfound
+}
+always ok {
+       rcode = ok
+       simulcount = 0
+       mpp = no
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  This file defines a number of instances of the "attr_filter" module.
+#
+
+# attr_filter - filters the attributes received in replies from
+# proxied servers, to make sure we send back to our RADIUS client
+# only allowed attributes.
+attr_filter attr_filter.post-proxy {
+       attrsfile = ${confdir}/attrs
+}
+
+# attr_filter - filters the attributes in the packets we send to
+# the RADIUS home servers.
+attr_filter attr_filter.pre-proxy {
+       attrsfile = ${confdir}/attrs.pre-proxy
+}
+
+# Enforce RFC requirements on the contents of Access-Reject
+# packets.  See the comments at the top of the file for
+# more details.
+#
+attr_filter attr_filter.access_reject {
+       key = %{User-Name}
+       attrsfile = ${confdir}/attrs.access_reject
+}
+
+#  Enforce RFC requirements on the contents of the
+#  Accounting-Response packets.  See the comments at the
+#  top of the file for more details.
+#
+attr_filter attr_filter.accounting_response {
+       key = %{User-Name}
+       attrsfile = ${confdir}/attrs.accounting_response
+}
+# -*- text -*-
+#
+#  $Id$
+
+#  rewrite arbitrary packets.  Useful in accounting and authorization.
+#
+#  As of 2.0, much of the functionality of this module is in "unlang".
+#  You should probably investigate using that before trying to use
+#  the "attr_rewrite" module.
+#
+#
+#  The module can also use the Rewrite-Rule attribute. If it
+#  is set and matches the name of the module instance, then
+#  that module instance will be the only one which runs.
+#
+#  Also if new_attribute is set to yes then a new attribute
+#  will be created containing the value replacewith and it
+#  will be added to searchin (packet, reply, proxy,
+#  proxy_reply or config).
+#
+# searchfor,ignore_case and max_matches will be ignored in that case.
+#
+# Backreferences are supported.
+#      %{0} will contain the string the whole match
+#      %{1} to %{8} will contain the contents of the 1st to
+#      the 8th parentheses
+#
+# If max_matches is greater than one, the backreferences will
+# correspond to the first attributed that matched.
+
+#
+attr_rewrite sanecallerid {
+       attribute = Called-Station-Id
+       # may be "packet", "reply", "proxy", "proxy_reply" or "config"
+       searchin = packet
+       searchfor = "[+ ]"
+       replacewith = ""
+       ignore_case = no
+       new_attribute = no
+       max_matches = 10
+
+       ## If set to yes then the replace string will be
+       ## appended to the original string
+       append = no
+}
+
+# -*- text -*-
+#
+#  $Id$
+
+# CHAP module
+#
+#  To authenticate requests containing a CHAP-Password attribute.
+#
+chap {
+       # no configuration
+}
+# -*- text -*-
+#
+#  $Id$
+
+#  A simple value checking module
+#
+#  As of 2.0, much of the functionality of this module is in "unlang".
+#  You should probably investigate using that before trying to use
+#  the "checkval" module.
+#
+#  It can be used to check if an attribute value in the request
+#  matches a (possibly multi valued) attribute in the check
+#  items This can be used for example for caller-id
+#  authentication.  For the module to run, both the request
+#  attribute and the check items attribute must exist
+#
+#  i.e.
+#  A user has an ldap entry with 2 radiusCallingStationId
+#  attributes with values "12345678" and "12345679".  If we
+#  enable rlm_checkval, then any request which contains a
+#  Calling-Station-Id with one of those two values will be
+#  accepted.  Requests with other values for
+#  Calling-Station-Id will be rejected.
+#
+#  Regular expressions in the check attribute value are allowed
+#  as long as the operator is '=~'
+#
+checkval {
+       # The attribute to look for in the request
+       item-name = Calling-Station-Id
+
+       # The attribute to look for in check items. Can be multi valued
+       check-name = Calling-Station-Id
+
+       # The data type. Can be
+       # string,integer,ipaddr,date,abinary,octets
+       data-type = string
+
+       # If set to yes and we dont find the item-name attribute in the
+       # request then we send back a reject
+       # DEFAULT is no
+       #notfound-reject = no
+}
+       
+# -*- text -*-
+#
+#  $Id$
+
+#  counter module:
+#  This module takes an attribute (count-attribute).
+#  It also takes a key, and creates a counter for each unique
+#  key.  The count is incremented when accounting packets are
+#  received by the server.  The value of the increment depends
+#  on the attribute type.
+#  If the attribute is Acct-Session-Time or of an integer type we add
+#  the value of the attribute. If it is anything else we increase the
+#  counter by one.
+#
+#  The 'reset' parameter defines when the counters are all reset to
+#  zero.  It can be hourly, daily, weekly, monthly or never.
+#
+#  hourly: Reset on 00:00 of every hour
+#  daily: Reset on 00:00:00 every day
+#  weekly: Reset on 00:00:00 on sunday
+#  monthly: Reset on 00:00:00 of the first day of each month
+#
+#  It can also be user defined. It should be of the form:
+#  num[hdwm] where:
+#  h: hours, d: days, w: weeks, m: months
+#  If the letter is ommited days will be assumed. In example:
+#  reset = 10h (reset every 10 hours)
+#  reset = 12  (reset every 12 days)
+#
+#
+#  The check-name attribute defines an attribute which will be
+#  registered by the counter module and can be used to set the
+#  maximum allowed value for the counter after which the user
+#  is rejected.
+#  Something like:
+#
+#  DEFAULT Max-Daily-Session := 36000
+#          Fall-Through = 1
+#
+#  You should add the counter module in the instantiate
+#  section so that it registers check-name before the files
+#  module reads the users file.
+#
+#  If check-name is set and the user is to be rejected then we
+#  send back a Reply-Message and we log a Failure-Message in
+#  the radius.log
+#
+#  If the count attribute is Acct-Session-Time then on each
+#  login we send back the remaining online time as a
+#  Session-Timeout attribute ELSE and if the reply-name is
+#  set, we send back that attribute.  The reply-name attribute
+#  MUST be of an integer type.
+#
+#  The counter-name can also be used instead of using the check-name
+#  like below:
+#
+#  DEFAULT  Daily-Session-Time > 3600, Auth-Type = Reject
+#      Reply-Message = "You've used up more than one hour today"
+#
+#  The allowed-servicetype attribute can be used to only take
+#  into account specific sessions. For example if a user first
+#  logs in through a login menu and then selects ppp there will
+#  be two sessions. One for Login-User and one for Framed-User
+#  service type. We only need to take into account the second one.
+#
+#  The module should be added in the instantiate, authorize and
+#  accounting sections.  Make sure that in the authorize
+#  section it comes after any module which sets the
+#  'check-name' attribute.
+#
+counter daily {
+       filename = ${db_dir}/db.daily
+       key = User-Name
+       count-attribute = Acct-Session-Time
+       reset = daily
+       counter-name = Daily-Session-Time
+       check-name = Max-Daily-Session
+       reply-name = Session-Timeout
+       allowed-servicetype = Framed-User
+       cache-size = 5000
+}
+
+# -*- text -*-
+#
+#  $Id$
+
+# Write a detailed log of all accounting records received.
+#
+detail {
+       #  Note that we do NOT use NAS-IP-Address here, as
+       #  that attribute MAY BE from the originating NAS, and
+       #  NOT from the proxy which actually sent us the
+       #  request.  The Client-IP-Address attribute is ALWAYS
+       #  the address of the client which sent us the
+       #  request.
+       #
+       #  The following line creates a new detail file for
+       #  every radius client (by IP address or hostname).
+       #  In addition, a new detail file is created every
+       #  day, so that the detail file doesn't have to go
+       #  through a 'log rotation'
+       #
+       #  If your detail files are large, you may also want
+       #  to add a ':%H' (see doc/variables.txt) to the end
+       #  of it, to create a new detail file every hour, e.g.:
+       #
+       #   ..../detail-%Y%m%d:%H
+       #
+       #  This will create a new detail file for every hour.
+       #
+       detailfile = ${radacctdir}/%{Client-IP-Address}/detail-%Y%m%d
+
+       #
+       #  The Unix-style permissions on the 'detail' file.
+       #
+       #  The detail file often contains secret or private
+       #  information about users.  So by keeping the file
+       #  permissions restrictive, we can prevent unwanted
+       #  people from seeing that information.
+       detailperm = 0600
+
+       #
+       #  Every entry in the detail file has a header which
+       #  is a timestamp.  By default, we use the ctime
+       #  format (see "man ctime" for details).
+       #
+       #  The header can be customized by editing this
+       #  string.  See "doc/variables.txt" for a description
+       #  of what can be put here.
+       #
+       header = "%t"
+
+       #
+       # Certain attributes such as User-Password may be
+       # "sensitive", so they should not be printed in the
+       # detail file.  This section lists the attributes
+       # that should be suppressed.
+       #
+       # The attributes should be listed one to a line.
+       #
+       #suppress {
+               # User-Password
+       #}
+
+}
+# -*- text -*-
+#
+#  Detail file writer, used in the following examples:
+#
+#      raddb/sites-available/robust-proxy-accounting
+#      raddb/sites-available/decoupled-accounting
+#
+#  Note that this module can write detail files that are read by
+#  only ONE "listen" section.  If you use BOTH of the examples
+#  above, you will need to define TWO "detail" modules.
+#
+#  e.g. detail1.example.com && detail2.example.com
+#
+#
+#  We write *multiple* detail files here.  They will be processed by
+#  the detail "listen" section in the order that they were created.
+#  The directory containing these files should NOT be used for any
+#  other purposes.  i.e. It should have NO other files in it.
+#
+#  Writing multiple detail enables the server to process the pieces
+#  in smaller chunks.  This helps in certain catastrophic corner cases.
+#
+#  $Id$
+#
+detail detail.example.com {
+       detailfile = ${radacctdir}/detail.example.com/detail-%Y%m%d:%H
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  More examples of doing detail logs.
+
+#
+#  Many people want to log authentication requests.
+#  Rather than modifying the server core to print out more
+#  messages, we can use a different instance of the 'detail'
+#  module, to log the authentication requests to a file.
+#
+#  You will also need to un-comment the 'auth_log' line
+#  in the 'authorize' section, below.
+#
+detail auth_log {
+       detailfile = ${radacctdir}/%{Client-IP-Address}/auth-detail-%Y%m%d
+
+       #
+       #  This MUST be 0600, otherwise anyone can read
+       #  the users passwords!
+       detailperm = 0600
+
+       # You may also strip out passwords completely
+       suppress {
+               User-Password
+       }
+}
+
+#
+#  This module logs authentication reply packets sent
+#  to a NAS.  Both Access-Accept and Access-Reject packets
+#  are logged.
+#
+#  You will also need to un-comment the 'reply_log' line
+#  in the 'post-auth' section, below.
+#
+detail reply_log {
+       detailfile = ${radacctdir}/%{Client-IP-Address}/reply-detail-%Y%m%d
+
+       detailperm = 0600
+}
+
+#
+#  This module logs packets proxied to a home server.
+#
+#  You will also need to un-comment the 'pre_proxy_log' line
+#  in the 'pre-proxy' section, below.
+#
+detail pre_proxy_log {
+       detailfile = ${radacctdir}/%{Client-IP-Address}/pre-proxy-detail-%Y%m%d
+
+       #
+       #  This MUST be 0600, otherwise anyone can read
+       #  the users passwords!
+       detailperm = 0600
+
+       # You may also strip out passwords completely
+       #suppress {
+               # User-Password
+       #}
+}
+
+#
+#  This module logs response packets from a home server.
+#
+#  You will also need to un-comment the 'post_proxy_log' line
+#  in the 'post-proxy' section, below.
+#
+detail post_proxy_log {
+       detailfile = ${radacctdir}/%{Client-IP-Address}/post-proxy-detail-%Y%m%d
+
+       detailperm = 0600
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  The 'digest' module currently has no configuration.
+#
+#  "Digest" authentication against a Cisco SIP server.
+#  See 'doc/rfc/draft-sterman-aaa-sip-00.txt' for details
+#  on performing digest authentication for Cisco SIP servers.
+#
+digest {
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  This is a more general example of the execute module.
+#
+#  This one is called "echo".
+#
+#  Attribute-Name = `%{echo:/path/to/program args}`
+#
+#  If you wish to execute an external program in more than
+#  one section (e.g. 'authorize', 'pre_proxy', etc), then it
+#  is probably best to define a different instance of the
+#  'exec' module for every section.    
+#
+#  The return value of the program run determines the result
+#  of the exec instance call as follows:
+#  (See doc/configurable_failover for details)
+#
+#  < 0 : fail      the module failed
+#  = 0 : ok        the module succeeded
+#  = 1 : reject    the module rejected the user
+#  = 2 : fail      the module failed
+#  = 3 : ok        the module succeeded
+#  = 4 : handled   the module has done everything to handle the request
+#  = 5 : invalid   the user's configuration entry was invalid
+#  = 6 : userlock  the user was locked out
+#  = 7 : notfound  the user was not found
+#  = 8 : noop      the module did nothing
+#  = 9 : updated   the module updated information in the request
+#  > 9 : fail      the module failed
+#
+exec echo {
+       #
+       #  Wait for the program to finish.
+       #
+       #  If we do NOT wait, then the program is "fire and
+       #  forget", and any output attributes from it are ignored.
+       #
+       #  If we are looking for the program to output
+       #  attributes, and want to add those attributes to the
+       #  request, then we MUST wait for the program to
+       #  finish, and therefore set 'wait=yes'
+       #
+       # allowed values: {no, yes}
+       wait = yes
+
+       #
+       #  The name of the program to execute, and it's
+       #  arguments.  Dynamic translation is done on this
+       #  field, so things like the following example will
+       #  work.
+       #
+       program = "/bin/echo %{User-Name}"
+
+       #
+       #  The attributes which are placed into the
+       #  environment variables for the program.
+       #
+       #  Allowed values are:
+       #
+       #       request         attributes from the request
+       #       config          attributes from the configuration items list
+       #       reply           attributes from the reply
+       #       proxy-request   attributes from the proxy request
+       #       proxy-reply     attributes from the proxy reply
+       #
+       #  Note that some attributes may not exist at some
+       #  stages.  e.g. There may be no proxy-reply
+       #  attributes if this module is used in the
+       #  'authorize' section.
+       #
+       input_pairs = request
+
+       #
+       #  Where to place the output attributes (if any) from
+       #  the executed program.  The values allowed, and the
+       #  restrictions as to availability, are the same as
+       #  for the input_pairs.
+       #
+       output_pairs = reply
+
+       #
+       #  When to execute the program.  If the packet
+       #  type does NOT match what's listed here, then
+       #  the module does NOT execute the program.
+       #
+       #  For a list of allowed packet types, see
+       #  the 'dictionary' file, and look for VALUEs
+       #  of the Packet-Type attribute.
+       #
+       #  By default, the module executes on ANY packet.
+       #  Un-comment out the following line to tell the
+       #  module to execute only if an Access-Accept is
+       #  being sent to the NAS.
+       #
+       #packet_type = Access-Accept
+
+       #
+       #  Should we escape the environment variables?
+       #  
+       #  If this is set, all the RADIUS attributes
+       #  are capitalised and dashes replaced with
+       #  underscores. Also, RADIUS values are surrounded
+       #  with double-quotes.
+       #
+       #  That is to say: User-Name=BobUser => USER_NAME="BobUser"
+       shell_escape = yes
+
+}
+# -*- text -*-
+#
+#  $Id$
+
+#  "passwd" configuration, for the /etc/group file. Adds a Etc-Group-Name
+#  attribute for every group that the user is member of.
+#
+#  You will have to define the Etc-Group-Name in the 'dictionary' file
+#  as a 'string' type.
+#
+#  The Group-Name attribute is automatically created by the Unix module,
+#  and does checking against /etc/group automatically.
+#
+#  i.e. this module should NOT be used as-is, but should be edited to
+#  point to a different group file.
+#
+passwd etc_group {
+       filename = /etc/group
+       format = "=Etc-Group-Name:::*,User-Name"
+       hashsize = 50
+       ignorenislike = yes
+       allowmultiplekeys = yes
+       delimiter = ":"
+}
+
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  Execute external programs
+#
+#  This module is useful only for 'xlat'.  To use it,
+#  put 'exec' into the 'instantiate' section.  You can then
+#  do dynamic translation of attributes like:
+#
+#  Attribute-Name = `%{exec:/path/to/program args}`
+#
+#  The value of the attribute will be replaced with the output
+#  of the program which is executed.  Due to RADIUS protocol
+#  limitations, any output over 253 bytes will be ignored.
+#
+#  The RADIUS attributes from the user request will be placed
+#  into environment variables of the executed program, as
+#  described in "man unlang" and in doc/variables.txt
+#
+#  See also "echo" for more sample configuration.
+#
+exec {
+       wait = no
+       input_pairs = request
+       shell_escape = yes
+       output = none
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+# The expiration module. This handles the Expiration attribute
+# It should be included in the *end* of the authorize section
+# in order to handle user Expiration. It should also be included
+# in the instantiate section in order to register the Expiration
+# compare function
+#
+expiration {
+       #
+       # The Reply-Message which will be sent back in case the
+       # account has expired. Dynamic substitution is supported
+       #
+       reply-message = "Password Has Expired\r\n" 
+       #reply-message = "Your account has expired, %{User-Name}\r\n"
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  The 'expression' module currently has no configuration.
+#
+#  This module is useful only for 'xlat'.  To use it,
+#  put 'expr' into the 'instantiate' section.  You can then
+#  do dynamic translation of attributes like:
+#
+#  Attribute-Name = `%{expr:2 + 3 + %{exec: uid -u}}`
+#
+#  The value of the attribute will be replaced with the output
+#  of the program which is executed.  Due to RADIUS protocol
+#  limitations, any output over 253 bytes will be ignored.
+#
+#  The module also registers a few paircompare functions
+expr {
+}
+# -*- text -*-
+#
+#  $Id$
+
+# Livingston-style 'users' file
+#
+files {
+       # The default key attribute to use for matches.  The content
+       # of this attribute is used to match the "name" of the
+       # entry.
+       #key = "%{Stripped-User-Name:-%{User-Name}}"
+
+       usersfile = ${confdir}/users
+       acctusersfile = ${confdir}/acct_users
+       preproxy_usersfile = ${confdir}/preproxy_users
+
+       #  If you want to use the old Cistron 'users' file
+       #  with FreeRADIUS, you should change the next line
+       #  to 'compat = cistron'.  You can the copy your 'users'
+       #  file from Cistron.
+       compat = no
+}
+# -*- text -*-
+#
+#  $Id$
+
+#  Do server side ip pool management. Should be added in
+#  post-auth and accounting sections.
+#
+#  The module also requires the existance of the Pool-Name
+#  attribute. That way the administrator can add the Pool-Name
+#  attribute in the user profiles and use different pools for
+#  different users. The Pool-Name attribute is a *check* item
+#  not a reply item.
+#
+#  The Pool-Name should be set to the ippool module instance
+#  name or to DEFAULT to match any module.
+
+#
+# Example:
+# radiusd.conf: ippool students { [...] }
+#              ippool teachers { [...] }
+# users file  : DEFAULT Group == students, Pool-Name := "students"
+#              DEFAULT Group == teachers, Pool-Name := "teachers"
+#              DEFAULT Group == other, Pool-Name := "DEFAULT"
+#
+# ********* IF YOU CHANGE THE RANGE PARAMETERS YOU MUST *********
+# ********* THEN ERASE THE DB FILES                     *********
+#
+ippool main_pool {
+
+       #  range-start,range-stop:
+       #       The start and end ip addresses for this pool.
+       range-start = 192.168.1.1
+       range-stop = 192.168.3.254
+
+       #  netmask:
+       #       The network mask used for this pool.
+       netmask = 255.255.255.0
+
+       #  cache-size:
+       #       The gdbm cache size for the db files. Should
+       #       be equal to the number of ip's available in
+       #       the ip pool
+       cache-size = 800
+
+       # session-db:
+       #       The main db file used to allocate addresses.
+       session-db = ${db_dir}/db.ippool
+
+       # ip-index:
+       #       Helper db index file used in multilink
+       ip-index = ${db_dir}/db.ipindex
+
+       # override:
+       #       If set, the Framed-IP-Address already in the
+       #       reply (if any) will be discarded, and replaced
+       #       with a Framed-IP-Address assigned here.
+       override = no
+
+       # maximum-timeout:
+       #       Specifies the maximum time in seconds that an
+       #       entry may be active.  If set to zero, means
+       #       "no timeout".  The default value is 0
+       maximum-timeout = 0
+
+       # key:
+       #       The key to use for the session database (which
+       #       holds the allocated ip's) normally it should
+       #       just be the nas ip/port (which is the default).
+       #
+       #       If your NAS sends the same value of NAS-Port
+       #       all requests, the key should be based on some
+       #       other attribute that is in ALL requests, AND
+       #       is unique to each machine needing an IP address.
+       #key = "%{NAS-IP-Address} %{NAS-Port}"
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  Kerberos.  See doc/rlm_krb5 for minimal docs.
+#
+krb5 {
+       keytab = /path/to/keytab
+       service_principal = name_of_principle
+}
+# -*- text -*-
+#
+#  $Id$
+
+# Lightweight Directory Access Protocol (LDAP)
+#
+#  This module definition allows you to use LDAP for
+#  authorization and authentication.
+#
+#  See raddb/sites-available/default for reference to the
+#  ldap module in the authorize and authenticate sections.
+#
+#  However, LDAP can be used for authentication ONLY when the
+#  Access-Request packet contains a clear-text User-Password
+#  attribute.  LDAP authentication will NOT work for any other
+#  authentication method.
+#
+#  This means that LDAP servers don't understand EAP.  If you
+#  force "Auth-Type = LDAP", and then send the server a
+#  request containing EAP authentication, then authentication
+#  WILL NOT WORK.
+#
+#  The solution is to use the default configuration, which does
+#  work.
+#
+#  Setting "Auth-Type = LDAP" is ALMOST ALWAYS WRONG.  We
+#  really can't emphasize this enough.
+#      
+ldap {
+       #
+       #  Note that this needs to match the name in the LDAP
+       #  server certificate, if you're using ldaps.
+       server = "ldap.your.domain"
+       #identity = "cn=admin,o=My Org,c=UA"
+       #password = mypass
+       basedn = "o=My Org,c=UA"
+       filter = "(uid=%{Stripped-User-Name:-%{User-Name}})"
+       #base_filter = "(objectclass=radiusprofile)"
+
+       #  How many connections to keep open to the LDAP server.
+       #  This saves time over opening a new LDAP socket for
+       #  every authentication request.
+       ldap_connections_number = 5
+
+       # seconds to wait for LDAP query to finish. default: 20
+       timeout = 4
+
+       #  seconds LDAP server has to process the query (server-side
+       #  time limit). default: 20
+       #
+       #  LDAP_OPT_TIMELIMIT is set to this value.
+       timelimit = 3
+
+       #
+       #  seconds to wait for response of the server. (network
+       #   failures) default: 10
+       #
+       #  LDAP_OPT_NETWORK_TIMEOUT is set to this value.
+       net_timeout = 1
+
+       #
+       #  This subsection configures the tls related items
+       #  that control how FreeRADIUS connects to an LDAP
+       #  server.  It contains all of the "tls_*" configuration
+       #  entries used in older versions of FreeRADIUS.  Those
+       #  configuration entries can still be used, but we recommend
+       #  using these.
+       #
+       tls {
+               # Set this to 'yes' to use TLS encrypted connections
+               # to the LDAP database by using the StartTLS extended
+               # operation.
+               #                       
+               # The StartTLS operation is supposed to be
+               # used with normal ldap connections instead of
+               # using ldaps (port 689) connections
+               start_tls = no
+
+               # cacertfile    = /path/to/cacert.pem
+               # cacertdir             = /path/to/ca/dir/
+               # certfile              = /path/to/radius.crt
+               # keyfile               = /path/to/radius.key
+               # randfile              = /path/to/rnd
+
+               #  Certificate Verification requirements.  Can be:
+               #    "never" (don't even bother trying)
+               #    "allow" (try, but don't fail if the cerificate
+               #               can't be verified)
+               #    "demand" (fail if the certificate doesn't verify.)
+               #
+               #       The default is "allow"
+               # require_cert  = "demand"
+       }
+
+       # default_profile = "cn=radprofile,ou=dialup,o=My Org,c=UA"
+       # profile_attribute = "radiusProfileDn"
+       # access_attr = "dialupAccess"
+
+       # Mapping of RADIUS dictionary attributes to LDAP
+       # directory attributes.
+       dictionary_mapping = ${confdir}/ldap.attrmap
+
+       #  Set password_attribute = nspmPassword to get the
+       #  user's password from a Novell eDirectory
+       #  backend. This will work ONLY IF FreeRADIUS has been
+       #  built with the --with-edir configure option.
+       #
+       #  See also the following links:
+       #
+       #  http://www.novell.com/coolsolutions/appnote/16745.html
+       #  https://secure-support.novell.com/KanisaPlatform/Publishing/558/3009668_f.SAL_Public.html
+       #
+       #  Novell may require TLS encrypted sessions before returning
+       #  the user's password.
+       #
+       # password_attribute = userPassword
+
+       #  Un-comment the following to disable Novell
+       #  eDirectory account policy check and intruder
+       #  detection. This will work *only if* FreeRADIUS is
+       #  configured to build with --with-edir option.
+       #
+       edir_account_policy_check = no
+
+       #
+       #  Group membership checking.  Disabled by default.
+       #
+       # groupname_attribute = cn
+       # groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{Ldap-UserDn})))"
+       # groupmembership_attribute = radiusGroupName
+
+       # compare_check_items = yes
+       # do_xlat = yes
+       # access_attr_used_for_allow = yes
+
+       #
+       #  By default, if the packet contains a User-Password,
+       #  and no other module is configured to handle the
+       #  authentication, the LDAP module sets itself to do
+       #  LDAP bind for authentication.
+       #
+       #  THIS WILL ONLY WORK FOR PAP AUTHENTICATION.
+       #
+       #  THIS WILL NOT WORK FOR CHAP, MS-CHAP, or 802.1x (EAP). 
+       #
+       #  You can disable this behavior by setting the following
+       #  configuration entry to "no".
+       #
+       #  allowed values: {no, yes}
+       # set_auth_type = yes
+
+       #  ldap_debug: debug flag for LDAP SDK
+       #  (see OpenLDAP documentation).  Set this to enable
+       #  huge amounts of LDAP debugging on the screen.
+       #  You should only use this if you are an LDAP expert.
+       #
+       #       default: 0x0000 (no debugging messages)
+       #       Example:(LDAP_DEBUG_FILTER+LDAP_DEBUG_CONNS)
+       #ldap_debug = 0x0028 
+}
+# -*- text -*-
+#
+#  $Id$
+
+# The logintime module. This handles the Login-Time,
+# Current-Time, and Time-Of-Day attributes.  It should be
+# included in the *end* of the authorize section in order to
+# handle Login-Time checks. It should also be included in the
+# instantiate section in order to register the Current-Time
+# and Time-Of-Day comparison functions.
+#
+# When the Login-Time attribute is set to some value, and the
+# user has bene permitted to log in, a Session-Timeout is
+# calculated based on the remaining time.  See "doc/README".
+#
+logintime {
+       #
+       # The Reply-Message which will be sent back in case
+       # the account is calling outside of the allowed
+       # timespan. Dynamic substitution is supported.
+       #
+       reply-message = "You are calling outside your allowed timespan\r\n"
+       #reply-message = "Outside allowed timespan (%{control:Login-Time}), %{User-Name}\r\n"
+
+       # The minimum timeout (in seconds) a user is allowed
+       # to have. If the calculated timeout is lower we don't
+       # allow the logon. Some NASes do not handle values
+       # lower than 60 seconds well.
+       minimum-timeout = 60
+}
+
+# -*- text -*-
+#
+#  $Id$
+
+######################################################################
+#
+#  This next section is a sample configuration for the "passwd"
+#  module, that reads flat-text files.
+#
+#  The file is in the format <mac>,<ip>
+#
+#      00:01:02:03:04:05,192.168.1.100
+#      01:01:02:03:04:05,192.168.1.101
+#      02:01:02:03:04:05,192.168.1.102
+#
+#  This lets you perform simple static IP assignments from a flat-text
+#  file.  You will have to define lease times yourself.
+#
+######################################################################
+
+passwd mac2ip {
+       filename = ${confdir}/mac2ip
+       format = "*DHCP-Client-Hardware-Address:=DHCP-Your-IP-Address"
+       delimiter = ","
+}
+# -*- text -*-
+#
+#  $Id$
+
+#  A simple file to map a MAC address to a VLAN.
+#
+#  The file should be in the format MAC,VLAN
+#  the VLAN name cannot have spaces in it, for example:
+#
+#      00:01:02:03:04:05,VLAN1
+#      03:04:05:06:07:08,VLAN2
+#      ...
+#
+passwd mac2vlan {
+       filename = ${confdir}/mac2vlan
+       format = "*VMPS-Mac:=VMPS-VLAN-Name"
+       delimiter = ","
+}
+# -*- text -*-
+#
+#  $Id$
+
+# Microsoft CHAP authentication
+#
+#  This module supports MS-CHAP and MS-CHAPv2 authentication.
+#  It also enforces the SMB-Account-Ctrl attribute.
+#
+mschap {
+       #
+       #  If you are using /etc/smbpasswd, see the 'passwd'
+       #  module for an example of how to use /etc/smbpasswd
+
+       # if use_mppe is not set to no mschap will
+       # add MS-CHAP-MPPE-Keys for MS-CHAPv1 and
+       # MS-MPPE-Recv-Key/MS-MPPE-Send-Key for MS-CHAPv2
+       #
+       #use_mppe = no
+
+       # if mppe is enabled require_encryption makes
+       # encryption moderate
+       #
+       #require_encryption = yes
+
+       # require_strong always requires 128 bit key
+       # encryption
+       #
+       #require_strong = yes
+
+       # Windows sends us a username in the form of
+       # DOMAIN\user, but sends the challenge response
+       # based on only the user portion.  This hack
+       # corrects for that incorrect behavior.
+       #
+       #with_ntdomain_hack = no
+
+       # The module can perform authentication itself, OR
+       # use a Windows Domain Controller.  This configuration
+       # directive tells the module to call the ntlm_auth
+       # program, which will do the authentication, and return
+       # the NT-Key.  Note that you MUST have "winbindd" and
+       # "nmbd" running on the local machine for ntlm_auth
+       # to work.  See the ntlm_auth program documentation
+       # for details.
+       #
+       # If ntlm_auth is configured below, then the mschap
+       # module will call ntlm_auth for every MS-CHAP
+       # authentication request.  If there is a cleartext
+       # or NT hashed password available, you can set
+       # "MS-CHAP-Use-NTLM-Auth := No" in the control items,
+       # and the mschap module will do the authentication itself,
+       # without calling ntlm_auth.
+       #
+       # Be VERY careful when editing the following line!
+       #
+       # You can also try setting the user name as:
+       #
+       #       ... --username=%{mschap:User-Name} ...
+       #
+       # In that case, the mschap module will look at the User-Name
+       # attribute, and do prefix/suffix checks in order to obtain
+       # the "best" user name for the request.
+       #
+       #ntlm_auth = "/path/to/ntlm_auth --request-nt-key --username=%{Stripped-User-Name:-%{User-Name:-None}} --challenge=%{mschap:Challenge:-00} --nt-response=%{mschap:NT-Response:-00}"
+}
+# -*- text -*-
+#
+#  $Id$
+
+
+# Pluggable Authentication Modules
+#
+#  For Linux, see:
+#      http://www.kernel.org/pub/linux/libs/pam/index.html
+#
+#  WARNING: On many systems, the system PAM libraries have
+#           memory leaks!  We STRONGLY SUGGEST that you do not
+#          use PAM for authentication, due to those memory leaks.
+#
+pam {
+       #
+       #  The name to use for PAM authentication.
+       #  PAM looks in /etc/pam.d/${pam_auth_name}
+       #  for it's configuration.  See 'redhat/radiusd-pam'
+       #  for a sample PAM configuration file.
+       #
+       #  Note that any Pam-Auth attribute set in the 'authorize'
+       #  section will over-ride this one.
+       #
+       pam_auth = radiusd
+}
+# -*- text -*-
+#
+#  $Id$
+
+# PAP module to authenticate users based on their stored password
+#
+#  Supports multiple encryption/hash schemes.  See "man rlm_pap"
+#  for details.
+#
+#  The "auto_header" configuration item can be set to "yes".
+#  In this case, the module will look inside of the User-Password
+#  attribute for the headers {crypt}, {clear}, etc., and will
+#  automatically create the attribute on the right-hand side,
+#  with the correct value.  It will also automatically handle
+#  Base-64 encoded data, hex strings, and binary data.
+pap {
+       auto_header = no
+}
+# -*- text -*-
+#
+#  $Id$
+
+# passwd module allows to do authorization via any passwd-like
+# file and to extract any attributes from these modules
+#
+# parameters are:
+#   filename - path to filename
+#   format - format for filename record. This parameters
+#            correlates record in the passwd file and RADIUS
+#            attributes.
+#
+#            Field marked as '*' is key field. That is, the parameter
+#            with this name from the request is used to search for
+#            the record from passwd file
+#            Attribute marked as '=' is added to reply_itmes instead
+#            of default configure_itmes
+#           Attribute marked as '~' is added to request_items
+#
+#            Field marked as ',' may contain a comma separated list
+#            of attributes.
+#   hashsize - hashtable size. If 0 or not specified records are not
+#            stored in memory and file is red on every request.
+#   allowmultiplekeys - if few records for every key are allowed
+#   ignorenislike - ignore NIS-related records
+#   delimiter - symbol to use as a field separator in passwd file,
+#            for format ':' symbol is always used. '\0', '\n' are
+#           not allowed 
+#
+
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  Module implementing a DIFFERENT policy language.
+#  The syntax here is NOT "unlang", but something else.
+#
+#  See the "raddb/policy.txt" file for documentation and examples.
+#  There isn't much else in the way of documentation, sorry.
+#
+policy {
+       #  The only configuration item is a filename containing
+       #  the policies to execute.
+       #
+       #  When "policy" is listed in a section (e.g. "authorize"),
+       #  it will run a policy named for that section.
+       # 
+       filename = ${confdir}/policy.txt
+}
+
+# -*- text -*-
+#
+#  $Id$
+
+# Preprocess the incoming RADIUS request, before handing it off
+# to other modules.
+#
+#  This module processes the 'huntgroups' and 'hints' files.
+#  In addition, it re-writes some weird attributes created
+#  by some NASes, and converts the attributes into a form which
+#  is a little more standard.
+#
+preprocess {
+       huntgroups = ${confdir}/huntgroups
+       hints = ${confdir}/hints
+
+       # This hack changes Ascend's wierd port numberings
+       # to standard 0-??? port numbers so that the "+" works
+       # for IP address assignments.
+       with_ascend_hack = no
+       ascend_channels_per_line = 23
+
+       # Windows NT machines often authenticate themselves as
+       # NT_DOMAIN\username
+       #
+       # If this is set to 'yes', then the NT_DOMAIN portion
+       # of the user-name is silently discarded.
+       #
+       # This configuration entry SHOULD NOT be used.
+       # See the "realms" module for a better way to handle
+       # NT domains.
+       with_ntdomain_hack = no
+
+       # Specialix Jetstream 8500 24 port access server.
+       #
+       # If the user name is 10 characters or longer, a "/"
+       # and the excess characters after the 10th are
+       # appended to the user name.
+       #
+       # If you're not running that NAS, you don't need
+       # this hack.
+       with_specialix_jetstream_hack = no
+
+       # Cisco (and Quintum in Cisco mode) sends it's VSA attributes
+       # with the attribute name *again* in the string, like:
+       #
+       #   H323-Attribute = "h323-attribute=value".
+       #
+       # If this configuration item is set to 'yes', then
+       # the redundant data in the the attribute text is stripped
+       # out.  The result is:
+       #
+       #  H323-Attribute = "value"
+       #
+       # If you're not running a Cisco or Quintum NAS, you don't
+       # need this hack.
+       with_cisco_vsa_hack = no
+}
+# -*- text -*-
+#
+#  $Id$
+
+#  Write a 'utmp' style file, of which users are currently
+#  logged in, and where they've logged in from.
+#
+#  This file is used mainly for Simultaneous-Use checking,
+#  and also 'radwho', to see who's currently logged in.
+#
+radutmp {
+       #  Where the file is stored.  It's not a log file,
+       #  so it doesn't need rotating.
+       #
+       filename = ${logdir}/radutmp
+
+       #  The field in the packet to key on for the
+       #  'user' name,  If you have other fields which you want
+       #  to use to key on to control Simultaneous-Use,
+       #  then you can use them here.
+       #
+       #  Note, however, that the size of the field in the
+       #  'utmp' data structure is small, around 32
+       #  characters, so that will limit the possible choices
+       #  of keys.
+       #
+       #  You may want instead: %{Stripped-User-Name:-%{User-Name}}
+       username = %{User-Name}
+
+
+       #  Whether or not we want to treat "user" the same
+       #  as "USER", or "User".  Some systems have problems
+       #  with case sensitivity, so this should be set to
+       #  'no' to enable the comparisons of the key attribute
+       #  to be case insensitive.
+       #
+       case_sensitive = yes
+
+       #  Accounting information may be lost, so the user MAY
+       #  have logged off of the NAS, but we haven't noticed.
+       #  If so, we can verify this information with the NAS,
+       #
+       #  If we want to believe the 'utmp' file, then this
+       #  configuration entry can be set to 'no'.
+       #
+       check_with_nas = yes            
+
+       # Set the file permissions, as the contents of this file
+       # are usually private.
+       perm = 0600
+
+       callerid = "yes"
+}
+# -*- text -*-
+#
+#  $Id$
+
+# Realm module, for proxying.
+#
+#  You can have multiple instances of the realm module to
+#  support multiple realm syntaxs at the same time.  The
+#  search order is defined by the order that the modules are listed
+#  in the authorize and preacct sections.
+#
+#  Four config options:
+#      format         -  must be "prefix" or "suffix"
+#                        The special cases of "DEFAULT"
+#                        and "NULL" are allowed, too.
+#      delimiter      -  must be a single character
+
+#  'realm/username'
+#
+#  Using this entry, IPASS users have their realm set to "IPASS".
+realm IPASS {
+       format = prefix
+       delimiter = "/"
+}
+
+#  'username@realm'
+#
+realm suffix {
+       format = suffix
+       delimiter = "@"
+}
+
+#  'username%realm'
+#
+realm realmpercent {
+       format = suffix
+       delimiter = "%"
+}
+
+#
+#  'domain\user'
+#
+realm ntdomain {
+       format = prefix
+       delimiter = "\\"
+}      
+# -*- text -*-
+#
+#  $Id$
+
+#  An example configuration for using /etc/smbpasswd.
+#
+#  See the "passwd" file for documentation on the configuration items
+#  for this module.
+#
+passwd smbpasswd {
+       filename = /etc/smbpasswd
+       format = "*User-Name::LM-Password:NT-Password:SMB-Account-CTRL-TEXT::"
+       hashsize = 100
+       ignorenislike = no
+       allowmultiplekeys = no
+}
+# -*- text -*-
+#
+#  $Id$
+
+#
+#  The rlm_sql_log module appends the SQL queries in a log
+#  file which is read later by the radsqlrelay program.
+#
+#  This module only performs the dynamic expansion of the
+#  variables found in the SQL statements. No operation is
+#  executed on the database server. (this could be done
+#  later by an external program) That means the module is
+#  useful only with non-"SELECT" statements.
+#
+#  See rlm_sql_log(5) manpage.
+#
+#  This same functionality could also be implemented by logging
+#  to a "detail" file, reading that, and then writing to SQL.
+#  See raddb/sites-available/buffered-sql for an example.
+#
+sql_log {
+       path = "${radacctdir}/sql-relay"
+       acct_table = "radacct"
+       postauth_table = "radpostauth"
+       sql_user_name = "%{%{User-Name}:-DEFAULT}"
+
+       Start = "INSERT INTO ${acct_table} (AcctSessionId, UserName, \
+        NASIPAddress, FramedIPAddress, AcctStartTime, AcctStopTime, \
+        AcctSessionTime, AcctTerminateCause) VALUES                 \
+        ('%{Acct-Session-Id}', '%{User-Name}', '%{NAS-IP-Address}', \
+        '%{Framed-IP-Address}', '%S', '0', '0', '');"
+       Stop = "INSERT INTO ${acct_table} (AcctSessionId, UserName,  \
+        NASIPAddress, FramedIPAddress, AcctStartTime, AcctStopTime, \
+        AcctSessionTime, AcctTerminateCause) VALUES                 \
+        ('%{Acct-Session-Id}', '%{User-Name}', '%{NAS-IP-Address}', \
+        '%{Framed-IP-Address}', '0', '%S', '%{Acct-Session-Time}',  \
+        '%{Acct-Terminate-Cause}');"
+       Alive = "INSERT INTO ${acct_table} (AcctSessionId, UserName, \
+        NASIPAddress, FramedIPAddress, AcctStartTime, AcctStopTime, \
+        AcctSessionTime, AcctTerminateCause) VALUES                 \
+        ('%{Acct-Session-Id}', '%{User-Name}', '%{NAS-IP-Address}', \
+        '%{Framed-IP-Address}', '0', '0', '%{Acct-Session-Time}','');"
+
+       Post-Auth = "INSERT INTO ${postauth_table}                   \
+        (username, pass, reply, authdate) VALUES                    \
+        ('%{User-Name}', '%{User-Password:-Chap-Password}',         \
+        '%{reply:Packet-Type}', '%S');"
+}
+
+# -*- text -*-
+#
+#  $Id$
+
+# "Safe" radutmp - does not contain caller ID, so it can be
+# world-readable, and radwho can work for normal users, without
+# exposing any information that isn't already exposed by who(1).
+#
+# This is another 'instance' of the radutmp module, but it is given
+# then name "sradutmp" to identify it later in the "accounting"
+# section.
+radutmp sradutmp {
+       filename = ${logdir}/sradutmp
+       perm = 0644
+       callerid = "no"
+}
+# -*- text -*-
+#
+#  $Id$
+
+# Unix /etc/passwd style authentication
+#
+unix {
+       #  As of 1.1.0, the Unix module no longer reads,
+       #  or caches /etc/passwd, /etc/shadow, or /etc/group.
+       #  If you wish to cache those files, see the passwd
+       #  module.
+       #
+
+       #
+       #  The location of the "wtmp" file.
+       #  The only use for 'radlast'.  If you don't use
+       #  'radlast', then you can comment out this item.
+       #
+       #  Note that the radwtmp file may get large!  You should
+       #  rotate it (cp /dev/null radwtmp), or just not use it.
+       #
+       radwtmp = ${logdir}/radwtmp
+}
diff --git a/raddb/naslist b/raddb/naslist
new file mode 100644 (file)
index 0000000..5f31e9a
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# naslist      This file contains a list of NASes (Network Access Servers,
+#              also known as terminal servers) which we know.
+#
+#              Description of the fields:
+#
+#              * The first field is a valid hostname or IP address
+#                for the client.
+#              * The second field (seperated by blanks or tabs) is the 
+#                short name we use in the logfiles for this NAS.
+#              * The third field defines what type of device it is. Valid
+#                values are "cisco", "computone", "livingston", "max40xx", 
+#                 "multitech", "netserver", "pathras", "patton", "portslave", 
+#                 "tc", "usrhiper" or "other".
+#
+#              This is used to find out how to detect double logins.
+#
+
+# NAS Name             Short Name      Type
+#----------------      ----------      ----
+#portmaster1.isp.com   pm1.NY          livingston
+#portmaster2.isp.com   pm1.LA          livingston
+localhost              local           portslave
+
diff --git a/raddb/naspasswd b/raddb/naspasswd
new file mode 100644 (file)
index 0000000..3ff89d6
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# naspasswd    This is the file that primarily stores the passwords
+#              for the NASes.  This will be read by checkrad.pl to
+#              supply the password for a certain NAS if needed, in the
+#              event that Cistron Radiusd suspects a multiple login.
+#
+#              Note that at this time you ONLY need to enter passwords
+#              here if you use a non-SNMP method to poll the terminal
+#              servers, eg ONLY with USR/3Com Total Control, NetServer 
+#              and Cyclades PathRAS servers!
+#
+#              This is in the format:
+#
+#                      ip_address<SPACE>login_name<SPACE>password
+#
+#              Blank lines and lines with '#' as the first
+#              character are ignored.
+#
+# WARNING:     Always make sure that this file has the "-r------" permission.
+#              And, don't set the passwords on your other systems to the same
+#              passwords that can be found below.
+#
+#
+
+#203.172.90.118 !root TufFseCrET
+#203.172.42.152 !root ToTaLCnTl
+
diff --git a/raddb/realms b/raddb/realms
new file mode 100644 (file)
index 0000000..a2ce264
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# realms       This file contains a list of realms. When a user logs
+#              in with @realm as the last part of the loginname,
+#              the realm part is looked up in this file. If found,
+#              the request is sent to the listed remote radius server.
+#
+#              Description of the fields:
+#
+#              * The first field is a realm name.
+#                The realm DEFAULT matches all realms.
+#              * The second field is a hostname. Optional is :port to
+#                use a non-standard port. In that case, port is the
+#                authentication port and the accounting port is taken
+#                as port + 1.
+#                If this field is set to LOCAL, the request is processed
+#                normally without sending it to a remote radius server.
+#              * Extra fields with options can follow. Currently
+#                defined options:
+#                - nostrip     do not strip @realm from the username
+#
+
+# Realm                 Remote server [:port]          Options
+#----------------      ---------------------           -------
+#isp2.com              radius.isp2.com                 nostrip
+#company.com           radius.company.com:1600
+#bla.com               LOCAL
+
diff --git a/raddb/users b/raddb/users
new file mode 100644 (file)
index 0000000..cac56c2
--- /dev/null
@@ -0,0 +1,156 @@
+#
+#      This file contains security and configuration information
+#      for each user.  The first field is the user's name and
+#      can be up to 8 characters in length.  This is followed (on
+#      the same line) with the list of authentication requirements
+#      for that user.  This can include password, comm server name,
+#      comm server port number, protocol type (perhaps set by the "hints"
+#      file), and huntgroup name (set by the "huntgroups" file).
+#
+#      When an authentication request is received from the comm server,
+#      these values are tested. Only the first match is used unless the
+#      "Fall-Through" variable is set to "Yes".
+#
+#      A special user named "DEFAULT" matches on all usernames.
+#      You can have several DEFAULT entries. All entries are processed
+#      in the order they appear in this file. The first entry that
+#      matches the login-request will stop processing unless you use
+#      the Fall-Through variable.
+#
+#      If you use the database support to turn this file into a .db or .dbm
+#      file, the DEFAULT entries _have_ to be at the end of this file and
+#      you can't have multiple entries for one username.
+#
+#      You don't need to specify a password if you set Auth-Type = System
+#      on the list of authentication requirements. The RADIUS server
+#      will then check the system password file.
+#
+#      Indented (with the tab character) lines following the first
+#      line indicate the configuration values to be passed back to
+#      the comm server to allow the initiation of a user session.
+#      This can include things like the PPP configuration values
+#      or the host to log the user onto.
+#
+#      You can include another `users' file with `$INCLUDE users.other'
+#
+
+#
+# This is a complete entry for "steve". Note that there is no Fall-Through
+# entry so that no DEFAULT entry will be used.
+#
+#steve Auth-Type = Local, Password = "testing"
+#      Service-Type = Framed-User,
+#      Framed-Protocol = PPP,
+#      Framed-IP-Address = 172.16.3.33,
+#      Framed-IP-Netmask = 255.255.255.0,
+#      Framed-Routing = Broadcast-Listen,
+#      Framed-Filter-Id = "std.ppp",
+#      Framed-MTU = 1500,
+#      Framed-Compression = Van-Jacobsen-TCP-IP
+
+#
+# Dial user back and telnet to the default host for that port
+#
+#Deg   Auth-Type = Local, Password = "ge55ged"
+#      Service-Type = Callback-Login-User,
+#      Login-IP-Host = 0.0.0.0,
+#      Callback-Number = "9,5551212",
+#      Login-Service = Telnet,
+#      Login-TCP-Port = 23
+
+#
+# Another complete entry. After the user "dialbk" has logged in, the
+# connection will be broken and the user will be dialed back after which
+# he will get a connection to the host "timeshare1".
+#
+#dialbk        Auth-Type = Local, Password = "callme"
+#      Service-Type = Callback-Login-User,
+#      Login-IP-Host = timeshare1,
+#      Login-Service = PortMaster,
+#      Callback-Number = "9,1-800-555-1212"
+
+#
+# user "swilson" will only get a static IP number if he logs in with
+# a framed protocol on a terminal server in Alphen (see the huntgroups file).
+# Note that by setting "Fall-Through" the rest will be gotten from the
+# appropriate DEFAULT entry.
+#
+#swilson       Service-Type = Framed-User, Huntgroup-Name = "alphen"
+#              Framed-IP-Address = 192.168.1.65,
+#              Fall-Through = Yes
+
+#
+# The rest of this file contains the several DEFAULT entries.
+# DEFAULT entries match with all login names.
+# Note that DEFAULT entries can also Fall-Through (see first entry).
+# A name-value pair from a DEFAULT entry will _NEVER_ override
+# an already existing name-value pair.
+#
+
+#
+# First setup all accounts to be checked against the UNIX /etc/passwd.
+# (Unless a password was already given earlier in this file).
+#
+DEFAULT        Auth-Type = System
+       Fall-Through = 1
+
+#
+# Set up different IP address pools for the terminal servers.
+# Note that the "+" behind the IP address means that this is the "base"
+# IP address. The Port-Id (S0, S1 etc) will be added to it.
+#
+#DEFAULT       Service-Type = Framed-User, Huntgroup-Name = "alphen"
+#              Framed-IP-Address = 192.168.1.32+,
+#              Fall-Through = Yes
+
+#DEFAULT       Service-Type = Framed-User, Huntgroup-Name = "delft"
+#              Framed-IP-Address = 192.168.2.32+,
+#              Fall-Through = Yes
+
+#
+# Defaults for all framed connections.
+#
+DEFAULT        Service-Type = Framed-User
+       Framed-IP-Address = 255.255.255.254,
+       Framed-MTU = 576,
+       Service-Type = Framed-User,
+       Fall-Through = Yes
+
+#
+# Default for PPP: dynamic IP address, PPP mode, VJ-compression.
+# NOTE: we do not use Hint = "PPP", since PPP might also be auto-detected
+#      by the terminal server in which case there may not be a "P" suffix.
+#      The terminal server sends "Framed-Protocol = PPP" for auto PPP.
+#
+DEFAULT        Framed-Protocol = PPP
+       Framed-Protocol = PPP,
+       Framed-Compression = Van-Jacobson-TCP-IP
+
+#
+# Default for CSLIP: dynamic IP address, SLIP mode, VJ-compression.
+#
+DEFAULT        Hint = "CSLIP"
+       Framed-Protocol = SLIP,
+       Framed-Compression = Van-Jacobson-TCP-IP
+
+#
+# Default for SLIP: dynamic IP address, SLIP mode.
+#
+DEFAULT        Hint = "SLIP"
+       Framed-Protocol = SLIP
+
+#
+# Last default: rlogin to our main server.
+#
+#DEFAULT
+#      Service-Type = Login-User,
+#      Login-Service = Rlogin,
+#      Login-IP-Host = shellbox.ispdomain.com
+
+# #
+# # Last default: shell on the local terminal server.
+# #
+# DEFAULT
+#      Service-Type = Shell-User
+
+# On no match, the user is denied access.
diff --git a/redhat/radiusd-cistron-1.5.4.3.spec b/redhat/radiusd-cistron-1.5.4.3.spec
new file mode 100644 (file)
index 0000000..bb9bdd8
--- /dev/null
@@ -0,0 +1,141 @@
+Summary: Cistron RADIUS daemon (with PAM) 
+Summary(pt_BR): Servidor RADIUS com muitas funcoes.
+Name: radiusd-cistron
+Version: 1.5.4.3
+Release: beta19
+Source: radiusd-cistron-1.5.4.3-beta19.tar.gz
+URL: http://www.miquels.cistron.nl/radius/
+Copyright: GPL
+Group: Networking/Daemons
+BuildRoot: /usr/tmp/radiusd
+
+%description
+RADIUS server with a lot of functions. Short overview: 
+
+- PAM support
+- Supports access based on huntgroups
+- Multiple DEFAULT entries in users file
+- All users file entries can optionally "fall through"
+- Caches all config files in-memory
+- Keeps a list of logged in users (radutmp file)
+- "radwho" program can be installed as "fingerd"
+- Logs both UNIX "wtmp" file format and RADIUS detail logfiles
+- Supports Simultaneous-Use = X parameter. Yes, this means
+  that you can now prevent double logins!
+
+%description -l pt_BR
+Servidor RADIUS com muitas funções. Visão geral:
+
+- Suporta acesso baseado em huntgroups
+- Multiplas entradas DEFAULT no arquivo de usuarios
+- Faz cache de todos os arquivos de configuracão em memoria
+- Mantem uma lista dos usuarios conectados (arquivo radutmp)
+- O programa radwho pode ser instalado como fingerd
+- Registra tanto no formato UNIX wtmp quanto no RADIUS detail
+- Suporta o parametro Simultaneous-Use = X. Sim, isto significa
+  que você pode evitar logins duplos!, inclusive com o Cyclades PathRas
+
+%changelog
+* Sat Nov 21 1998 Tim Hockin <thockin@ais.net>
+- Based on work by Christopher McCrory <chrismcc@netus.com>
+- Build with PAM
+- Included pam.d/radius
+- Fixed some small errors in this spec
+- Changed to build to BuildRoot
+- Changed Release to "beta11" from "1"
+- Included users, naslist, huntgroups, clients files, not just -dist
+
+* Tue Oct 27 1998 Mauricio Mello de Andrade <mandrade@mma.com.br>
+- Corrected the script to Start/Stop the Radius under RH5.x
+- Included the script to Rotate Radius Logs under RedHat
+- Checkrad Utility now works fine with Cyclades PathRas
+
+%prep 
+%setup
+cd raddb
+for f in clients users naslist huntgroups ; do cp $f $f-dist ; done
+cd ..
+
+%build
+./configure --prefix=/usr --localstatedir=/var --sysconfdir=/etc --with-pam
+make
+
+%install
+# prepare $RPM_BUILD_ROOT
+rm -rf $RPM_BUILD_ROOT
+mkdir $RPM_BUILD_ROOT/{,etc/{,raddb,logrotate.d,pam.d,rc.d/{,init.d,rc{0,1,2,3,4,5,6}.d}},usr/{,bin,sbin,man/{,man{1,5,8}}},var/{,log/{,radacct}}}
+
+# make install
+make install ROOT=${RPM_BUILD_ROOT}
+install -m 755 src/radtest ${RPM_BUILD_ROOT}/usr/bin/
+cd ..
+
+# do /etc/raddb
+cd raddb
+install -m 640 * ${RPM_BUILD_ROOT}/etc/raddb
+cd ..
+
+# radwatch
+install -m 755 scripts/radwatch ${RPM_BUILD_ROOT}/usr/sbin/
+
+# other files
+cd redhat
+install -m 555 rc.radiusd-redhat ${RPM_BUILD_ROOT}/etc/rc.d/init.d/radiusd.init
+install -m 644 radiusd-logrotate ${RPM_BUILD_ROOT}/etc/logrotate.d/radiusd
+install -m 644 radiusd-pam ${RPM_BUILD_ROOT}/etc/pam.d/radius
+cd ..
+
+# man pages
+cd doc
+for i in 1 8; do
+       install -m 444 *.$i ${RPM_BUILD_ROOT}/usr/man/man$i
+done
+install -m 444 clients.5rad ${RPM_BUILD_ROOT}/usr/man/man5/
+install -m 444 naslist.5rad ${RPM_BUILD_ROOT}/usr/man/man5/
+cd ..
+
+# rc.d files
+for i in 3 4 5;  do
+       ln -sf ../init.d/radiusd.init ${RPM_BUILD_ROOT}/etc/rc.d/rc$i.d/S88radiusd.init
+done
+for i in 0 1 2 6; do
+       ln -sf ../init.d/radiusd.init ${RPM_BUILD_ROOT}/etc/rc.d/rc$i.d/K12radiusd.init
+done
+
+for i in radutmp radwtmp radius.log; do
+       touch ${RPM_BUILD_ROOT}/var/log/$i
+       chown root.root ${RPM_BUILD_ROOT}/var/log/$i
+       mkdir -p /var/log/radacct
+done
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%doc doc/ChangeLog doc/README doc/README.pam doc/README.proxy 
+%doc doc/README.usersfile doc/README.simul doc/INSTALL.OLD 
+%doc doc/Makefile.README doc/README.cisco todo/ 
+%doc COPYRIGHT.Cistron COPYRIGHT.Livingston
+
+/usr/bin/*
+/usr/sbin/*
+/usr/man/man1/*
+/usr/man/man5/*
+/usr/man/man8/*
+/var/log/radutmp
+/var/log/radwtmp
+/var/log/radius.log
+%dir /var/log/radacct/
+
+%dir /etc/raddb/
+%config /etc/raddb/*
+%config /etc/pam.d/radius
+%config /etc/logrotate.d/radiusd
+%config /etc/rc.d/init.d/radiusd.init
+%config(missingok) /etc/rc.d/rc0.d/K12radiusd.init
+%config(missingok) /etc/rc.d/rc1.d/K12radiusd.init
+%config(missingok) /etc/rc.d/rc2.d/K12radiusd.init
+%config(missingok) /etc/rc.d/rc3.d/S88radiusd.init
+%config(missingok) /etc/rc.d/rc4.d/S88radiusd.init
+%config(missingok) /etc/rc.d/rc5.d/S88radiusd.init
+%config(missingok) /etc/rc.d/rc6.d/K12radiusd.init
diff --git a/redhat/radiusd-logrotate b/redhat/radiusd-logrotate
new file mode 100644 (file)
index 0000000..2976a16
--- /dev/null
@@ -0,0 +1,45 @@
+# You can use this to rotate the /var/log/radwtmp, simply copy it to
+# /etc/logrotate.d/radiusd
+
+# if you use defail files, You can uncomment the next block and
+# edit it accordling your /etc/raddb/naslist file. If you comment
+# the /var/log/radwtmp block you'll need to include the
+# postrotate/endscript parts to the *last* NAS-NAME/detail of this file
+
+#/var/log/radacct/NAS-NAME/detail {
+#      monthly
+#      rotate 4
+#      create
+#      compress
+#}
+
+/var/log/checkrad.log {
+        monthly
+        rotate 4
+        create
+        compress
+}
+
+/var/log/radius.log {
+        monthly
+        rotate 4
+        create
+        compress
+}
+
+/var/log/radwatch.log {
+        monthly
+        rotate 4
+        create
+        compress
+}
+
+/var/log/radwtmp {
+       monthly
+       rotate 4
+       create
+       compress
+       postrotate
+               /etc/rc.d/init.d/radiusd reload
+       endscript
+}
diff --git a/redhat/radiusd-pam b/redhat/radiusd-pam
new file mode 100644 (file)
index 0000000..d137b24
--- /dev/null
@@ -0,0 +1,7 @@
+#%PAM-1.0
+auth       required    /lib/security/pam_pwdb.so shadow nullok
+auth       required    /lib/security/pam_nologin.so
+account    required    /lib/security/pam_pwdb.so
+password   required    /lib/security/pam_cracklib.so
+password   required    /lib/security/pam_pwdb.so shadow nullok use_authtok
+session    required    /lib/security/pam_pwdb.so
diff --git a/redhat/rc.radiusd-redhat b/redhat/rc.radiusd-redhat
new file mode 100755 (executable)
index 0000000..2e0db4e
--- /dev/null
@@ -0,0 +1,58 @@
+#!/bin/sh
+# radiusd
+# radiusd      Start the radius daemon.
+#
+#              This is a script suitable for the Redhat Linux distribution.
+#              Copy it to /etc/rc.d/init.d/radiusd.init and
+#              use tksysv or your favorite runlevel editor to start it
+#              at runlevel 3
+#
+# chkconfig: 345 98 10
+# description: Ativa/Desativa servidor Radius
+
+
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+RADIUSD=/usr/sbin/radiusd
+WATCHER=/usr/sbin/radwatch
+LOCKF=/var/lock/subsys/radiusd
+
+test -f $RADIUSD || exit 0
+test -f /etc/raddb/clients || exit 0
+
+case "$1" in
+  start)
+       [ -f /var/log/radutmp ] || touch /var/log/radutmp
+       echo -n 'Starting RADIUSD server: '
+       if [ -x $WATCHER ]
+       then
+               daemon $WATCHER $RADIUSD -y
+       else
+               daemon $RADIUSD -y
+       fi
+       touch $LOCKF
+       echo "done."
+       ;;
+  stop)
+       echo -n 'Stopping RADIUSD server: '
+       if [ -x $WATCHER ]
+       then
+               killproc $WATCHER 2> /dev/null
+       fi
+       killproc $RADIUSD 2> /dev/null
+       echo "done."
+       rm -f $LOCKF
+       ;;
+  reload|restart)
+       $0 stop
+       sleep 3
+       $0 start
+       ;;
+  *)
+        echo "Usage: $0 {start|stop|reload}"
+        exit 1
+esac
+
+exit 0
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
new file mode 100644 (file)
index 0000000..a6bb984
--- /dev/null
@@ -0,0 +1,9 @@
+
+@INCLUDE@ @IQUOTE@../Make.inc@IQUOTE@
+
+all:
+
+install:
+
+clean:
+
diff --git a/scripts/radiusd.cron.daily b/scripts/radiusd.cron.daily
new file mode 100755 (executable)
index 0000000..15aaa4f
--- /dev/null
@@ -0,0 +1,31 @@
+#! /bin/sh
+#
+# radiusd      Cron script to rotate radiusd log files daily.
+#              Debian/Linux: place this in /etc/cron.daily.
+#
+
+umask 027
+cd /var/log
+
+# Take care of the standard logfiles.
+cd /var/log
+if [ -f radius.log ]
+then
+       savelog -g adm -m 640 -c 3 radius.log > /dev/null
+fi
+
+# Rotate "details" files.
+if [ ! -d radacct/. ]
+then
+       exit 0
+fi
+cd radacct
+
+for LOG in */detail
+do
+       if [ -f $LOG ]
+       then
+               savelog -g adm -m 640 -u root -c 3 $LOG >/dev/null
+       fi
+done
+
diff --git a/scripts/radiusd.cron.monthly b/scripts/radiusd.cron.monthly
new file mode 100755 (executable)
index 0000000..09bc990
--- /dev/null
@@ -0,0 +1,16 @@
+#! /bin/sh
+#
+# radiusd      Cron script to rotate radwtmp file monthly.
+#              Debian/Linux: place this in /etc/cron.monthly.
+#
+
+umask 022
+cd /var/log
+
+# Take care of the standard logfiles.
+cd /var/log
+if [ -f radwtmp ]
+then
+       savelog -g adm -m 644 -c 6 radwtmp > /dev/null
+fi
+
diff --git a/scripts/radwatch.in b/scripts/radwatch.in
new file mode 100755 (executable)
index 0000000..e261313
--- /dev/null
@@ -0,0 +1,51 @@
+#! /bin/sh
+#
+# radwatch     Script to watch RADIUS. Sends mail to root and
+#              restarts radiusd when it dies [which ofcourse
+#              never happens :)]
+#
+# Version:     @(#)radwatch  1.20  19-Jul-1999  miquels@cistron.nl
+#
+
+prefix          = @prefix@
+exec_prefix     = @exec_prefix@
+sbindir         = @sbindir@
+localstatedir   = @localstatedir@
+logdir          = @logdir@
+rundir          = ${localstatedir}/run
+
+MAILTO=root
+RADIUSD=$sbindir/radiusd
+
+exec >> $logdir/radwatch.log 2>&1
+
+# get the path to the radiusd
+if [ "$1" ] && [ -x "$1" ]
+then
+       RADIUSD=$1
+       shift
+fi
+
+cd $logdir
+[ -d $logdir/radacct ] && cd $logdir/radacct
+ulimit -c unlimited
+
+(
+       trap 'echo `date`: exit; kill `cat $rundir/radiusd.pid`; exit 0' TERM
+       trap "" HUP TSTP
+
+       while :
+       do
+               # Use `wait', otherwise the trap doesn't work.
+               $RADIUSD -f $* &
+               wait
+               exec >> $logdir/radwatch.log 2>&1
+               echo "`date`: Radius died, restarting.."
+               date | mail -s "Radius died, restarting.." $MAILTO
+               sleep 10
+       done
+) &
+
+echo "$!" > $rundir/radwatch.pid
+
+sleep 1
diff --git a/scripts/rc.radiusd.in b/scripts/rc.radiusd.in
new file mode 100755 (executable)
index 0000000..62a017f
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# radiusd      Start the radius daemon.
+#
+#              This is a script suitable for the Debian Linux distribution.
+#              Copy it to /etc/init.d/radiusd, make it executable, and
+#              execute "update-rc.d radiusd defaults 50".
+#
+
+prefix         = @prefix@
+exec_prefix    = @exec_prefix@
+sbindir                = @sbindir@
+localstatedir  = @localstatedir@
+logdir         = @logdir@
+rundir         = ${localstatedir}/run
+
+RADIUSD=$sbindir/radiusd
+WATCHER=$sbindir/radwatch
+DESC="Cistron radius server"
+NAME1=radiusd
+NAME2=radwatch
+
+ARGS="-y"
+
+test -f $RADIUSD || exit 0
+
+case "$1" in
+  start)
+       if [ ! -f $logdir/radutmp ]
+       then
+               :>$logdir/radutmp
+       fi
+       echo -n "Starting $DESC: "
+       if [ -x $WATCHER ]
+       then
+               echo -n "radwatch "
+               start-stop-daemon --start --quiet --startas $WATCHER \
+                       --pidfile $rundir/$NAME2.pid --exec $RADIUSD -- $ARGS
+       else
+               start-stop-daemon --start --quiet \
+                       --pidfile $rundir/$NAME1.pid --exec $RADIUSD -- $ARGS
+       fi
+       echo "radiusd."
+       ;;
+  stop)
+       [ -z "$2" ] && echo -n "Stopping $DESC: "
+       if [ -x $WATCHER ]
+       then
+               [ -z "$2" ] && echo -n "radwatch "
+               start-stop-daemon --stop --quiet \
+                       --pidfile $rundir/$NAME2.pid -- exec $RADWATCH
+               #killall -9 radwatch 2>/dev/null
+       else
+               start-stop-daemon --stop --quiet \
+                       --pidfile $rundir/$NAME1.pid --exec $RADIUSD
+       fi
+       #killall radiusd 2>/dev/null
+       [ -z "$2" ] && echo "radiusd."
+       ;;
+  reload|force-reload)
+       echo "Reloading $DESC configuration files."
+       start-stop-daemon --stop --signal 1 --quiet --pidfile \
+               $rundir/$NAME1.pid --exec $RADIUSD
+       ;;
+  restart)
+       sh /etc/init.d/radiusd stop quiet
+       sleep 3
+       /etc/init.d/radiusd start
+       ;;
+  *)
+        echo "Usage: /etc/init.d/$NAME1 {start|stop|reload|restart}"
+        exit 1
+esac
+
+exit 0
diff --git a/share/dictionary b/share/dictionary
new file mode 100644 (file)
index 0000000..4a20739
--- /dev/null
@@ -0,0 +1,249 @@
+#
+# Updated 07-Nov-1998 to RFC 2138 and RFC 2139
+#
+#      This file contains dictionary translations for parsing
+#      requests and generating responses.  All transactions are
+#      composed of Attribute/Value Pairs.  The value of each attribute
+#      is specified as one of 4 data types.  Valid data types are:
+#
+#      string - 0-253 octets
+#      ipaddr - 4 octets in network byte order
+#      integer - 32 bit value in big endian order (high byte first)
+#      date - 32 bit value in big endian order - seconds since
+#                                      00:00:00 GMT,  Jan.  1,  1970
+#
+#      Enumerated values are stored in the user file with dictionary
+#      VALUE translations for easy administration.
+#
+#      Example:
+#
+#      ATTRIBUTE         VALUE
+#      ---------------   -----
+#      Framed-Protocol = PPP
+#      7               = 1     (integer encoding)
+#
+
+#
+#      Include compatibility dictionary for older users file. Move this
+#      directive to the end of the file if you want to see the old names
+#      in the logfiles too.
+#
+$INCLUDE dictionary.compat
+$INCLUDE dictionary.livingston
+#$INCLUDE dictionary.tunnel
+#$INCLUDE dictionary.usr
+#$INCLUDE dictionary.ascend
+
+#
+#      Following are the proper new names. Use these.
+#
+ATTRIBUTE      User-Name               1       string
+ATTRIBUTE      Password                2       string
+ATTRIBUTE      CHAP-Password           3       string
+ATTRIBUTE      NAS-IP-Address          4       ipaddr
+ATTRIBUTE      NAS-Port-Id             5       integer
+ATTRIBUTE      Service-Type            6       integer
+ATTRIBUTE      Framed-Protocol         7       integer
+ATTRIBUTE      Framed-IP-Address       8       ipaddr
+ATTRIBUTE      Framed-IP-Netmask       9       ipaddr
+ATTRIBUTE      Framed-Routing          10      integer
+ATTRIBUTE      Filter-Id               11      string
+ATTRIBUTE      Framed-MTU              12      integer
+ATTRIBUTE      Framed-Compression      13      integer
+ATTRIBUTE      Login-IP-Host           14      ipaddr
+ATTRIBUTE      Login-Service           15      integer
+ATTRIBUTE      Login-TCP-Port          16      integer
+ATTRIBUTE      Reply-Message           18      string
+ATTRIBUTE      Callback-Number         19      string
+ATTRIBUTE      Callback-Id             20      string
+ATTRIBUTE      Framed-Route            22      string
+ATTRIBUTE      Framed-IPX-Network      23      ipaddr
+ATTRIBUTE      State                   24      string
+ATTRIBUTE      Class                   25      string
+ATTRIBUTE      Vendor-Specific         26      string
+ATTRIBUTE      Session-Timeout         27      integer
+ATTRIBUTE      Idle-Timeout            28      integer
+ATTRIBUTE      Termination-Action      29      integer
+ATTRIBUTE      Called-Station-Id       30      string
+ATTRIBUTE      Calling-Station-Id      31      string
+ATTRIBUTE      NAS-Identifier          32      string
+ATTRIBUTE      Proxy-State             33      string
+ATTRIBUTE      Login-LAT-Service       34      string
+ATTRIBUTE      Login-LAT-Node          35      string
+ATTRIBUTE      Login-LAT-Group         36      string
+ATTRIBUTE      Framed-AppleTalk-Link   37      integer
+ATTRIBUTE      Framed-AppleTalk-Network 38     integer
+ATTRIBUTE      Framed-AppleTalk-Zone   39      string
+
+ATTRIBUTE      Acct-Status-Type        40      integer
+ATTRIBUTE      Acct-Delay-Time         41      integer
+ATTRIBUTE      Acct-Input-Octets       42      integer
+ATTRIBUTE      Acct-Output-Octets      43      integer
+ATTRIBUTE      Acct-Session-Id         44      string
+ATTRIBUTE      Acct-Authentic          45      integer
+ATTRIBUTE      Acct-Session-Time       46      integer
+ATTRIBUTE       Acct-Input-Packets     47      integer
+ATTRIBUTE       Acct-Output-Packets    48      integer
+ATTRIBUTE      Acct-Terminate-Cause    49      integer
+ATTRIBUTE      Acct-Multi-Session-Id   50      string
+ATTRIBUTE      Acct-Link-Count         51      integer
+
+ATTRIBUTE      CHAP-Challenge          60      string
+ATTRIBUTE      NAS-Port-Type           61      integer
+ATTRIBUTE      Port-Limit              62      integer
+ATTRIBUTE      Login-LAT-Port          63      integer
+
+ATTRIBUTE      Connect-Info            77      string
+
+#
+#      Experimental Non Protocol Attributes used by Cistron-Radiusd
+#
+ATTRIBUTE      Huntgroup-Name          221     string
+ATTRIBUTE      User-Category           1029    string
+ATTRIBUTE      Group-Name              1030    string
+ATTRIBUTE      Simultaneous-Use        1034    integer
+ATTRIBUTE      Strip-User-Name         1035    integer
+ATTRIBUTE      Fall-Through            1036    integer
+ATTRIBUTE      Add-Port-To-IP-Address  1037    integer
+ATTRIBUTE      Exec-Program            1038    string
+ATTRIBUTE      Exec-Program-Wait       1039    string
+ATTRIBUTE      Hint                    1040    string
+ATTRIBUTE      Pam-Auth                1041    string
+ATTRIBUTE      Login-Time              1042    string
+
+#
+#      Non-Protocol Attributes
+#      These attributes are used internally by the server
+#
+ATTRIBUTE      Expiration                21    date
+ATTRIBUTE      Auth-Type               1000    integer
+ATTRIBUTE      Menu                    1001    string
+ATTRIBUTE      Termination-Menu        1002    string
+ATTRIBUTE      Prefix                  1003    string
+ATTRIBUTE      Suffix                  1004    string
+ATTRIBUTE      Group                   1005    string
+ATTRIBUTE      Crypt-Password          1006    string
+ATTRIBUTE      Connect-Rate            1007    integer
+
+#
+#      Integer Translations
+#
+
+#      User Types
+
+VALUE          Service-Type            Login-User              1
+VALUE          Service-Type            Framed-User             2
+VALUE          Service-Type            Callback-Login-User     3
+VALUE          Service-Type            Callback-Framed-User    4
+VALUE          Service-Type            Outbound-User           5
+VALUE          Service-Type            Administrative-User     6
+VALUE          Service-Type            NAS-Prompt-User         7
+VALUE          Service-Type            Call-Check              10
+
+#      Framed Protocols
+
+VALUE          Framed-Protocol         PPP                     1
+VALUE          Framed-Protocol         SLIP                    2
+
+#      Framed Routing Values
+
+VALUE          Framed-Routing          None                    0
+VALUE          Framed-Routing          Broadcast               1
+VALUE          Framed-Routing          Listen                  2
+VALUE          Framed-Routing          Broadcast-Listen        3
+
+#      Framed Compression Types
+
+VALUE          Framed-Compression      None                    0
+VALUE          Framed-Compression      Van-Jacobson-TCP-IP     1
+
+#      Login Services
+
+VALUE          Login-Service           Telnet                  0
+VALUE          Login-Service           Rlogin                  1
+VALUE          Login-Service           TCP-Clear               2
+VALUE          Login-Service           PortMaster              3
+
+#      Status Types
+
+VALUE          Acct-Status-Type        Start                   1
+VALUE          Acct-Status-Type        Stop                    2
+VALUE          Acct-Status-Type        Alive                   3
+VALUE          Acct-Status-Type        Accounting-On           7
+VALUE          Acct-Status-Type        Accounting-Off          8
+
+#      Authentication Types
+
+VALUE          Acct-Authentic          RADIUS                  1
+VALUE          Acct-Authentic          Local                   2
+
+#      Termination Options
+
+VALUE          Termination-Action      Default                 0
+VALUE          Termination-Action      RADIUS-Request          1
+
+#      NAS Port Types, available in 3.3.1 and later
+
+VALUE          NAS-Port-Type           Async                   0
+VALUE          NAS-Port-Type           Sync                    1
+VALUE          NAS-Port-Type           ISDN                    2
+VALUE          NAS-Port-Type           ISDN-V120               3
+VALUE          NAS-Port-Type           ISDN-V110               4
+
+#      Acct Terminate Causes, available in 3.3.2 and later
+
+VALUE           Acct-Terminate-Cause    User-Request            1
+VALUE           Acct-Terminate-Cause    Lost-Carrier            2
+VALUE           Acct-Terminate-Cause    Lost-Service            3
+VALUE           Acct-Terminate-Cause    Idle-Timeout            4
+VALUE           Acct-Terminate-Cause    Session-Timeout         5
+VALUE           Acct-Terminate-Cause    Admin-Reset             6
+VALUE           Acct-Terminate-Cause    Admin-Reboot            7
+VALUE           Acct-Terminate-Cause    Port-Error              8
+VALUE           Acct-Terminate-Cause    NAS-Error               9
+VALUE           Acct-Terminate-Cause    NAS-Request             10
+VALUE           Acct-Terminate-Cause    NAS-Reboot              11
+VALUE           Acct-Terminate-Cause    Port-Unneeded           12
+VALUE           Acct-Terminate-Cause    Port-Preempted          13
+VALUE           Acct-Terminate-Cause    Port-Suspended          14
+VALUE           Acct-Terminate-Cause    Service-Unavailable     15
+VALUE           Acct-Terminate-Cause    Callback                16
+VALUE           Acct-Terminate-Cause    User-Error              17
+VALUE           Acct-Terminate-Cause    Host-Request            18
+
+#VALUE         Tunnel-Type             L2TP                    3
+#VALUE         Tunnel-Medium-Type      IP                      1
+
+#
+#      Non-Protocol Integer Translations
+#
+
+VALUE          Auth-Type               Local                   0
+VALUE          Auth-Type               System                  1
+VALUE          Auth-Type               SecurID                 2
+VALUE          Auth-Type               Crypt-Local             3
+VALUE          Auth-Type               Reject                  4
+VALUE          Auth-Type               ActivCard               4
+
+#
+#      Cistron extensions
+#
+VALUE          Auth-Type               Pam                     253
+VALUE          Auth-Type               Accept                  254
+
+#
+#      Experimental Non-Protocol Integer Translations for Cistron-Radiusd
+#
+VALUE          Fall-Through            No                      0
+VALUE          Fall-Through            Yes                     1
+VALUE          Add-Port-To-IP-Address  No                      0
+VALUE          Add-Port-To-IP-Address  Yes                     1
+
+#
+#      Configuration Values
+#      comment out these two lines to turn account expiration off
+#
+
+VALUE          Server-Config           Password-Expiration     30
+VALUE          Server-Config           Password-Warning        5
+
diff --git a/share/dictionary.acc b/share/dictionary.acc
new file mode 100644 (file)
index 0000000..6aeee91
--- /dev/null
@@ -0,0 +1,229 @@
+#
+# dictionary.acc
+#              Dictionary for Acc/Newbridge, models Tigris, Amazon, etc.
+#              Written by Stephane Marzloff <smarzloff@carif-idf.org>
+#              based on specifications available through ftp and the web.
+#
+# Version:     @(#)dictionary.acc  1.00  smarzloff  21-Jun-1999
+#
+
+VENDOR Acc     5
+
+#
+# Acc specific
+ATTRIBUTE      Acc-Reason-Code                 1       integer         Acc
+ATTRIBUTE      Acc-Ccp-Option                  2       integer         Acc
+ATTRIBUTE      Acc-Input-Errors                3       integer         Acc
+ATTRIBUTE      Acc-Output-Errors               4       integer         Acc
+ATTRIBUTE      Acc-Access-Partition            5       string          Acc
+ATTRIBUTE      Acc-Customer-Id                 6       string          Acc
+ATTRIBUTE      Acc-Ip-Gateway-Pri              7       ipaddr          Acc
+ATTRIBUTE      Acc-Ip-Gateway-Sec              8       ipaddr          Acc
+ATTRIBUTE      Acc-Route-Policy                9       integer         Acc
+ATTRIBUTE      Acc-ML-MLX-Admin-State          10      integer         Acc
+ATTRIBUTE      Acc-ML-Call-Threshold           11      integer         Acc
+ATTRIBUTE      Acc-ML-Clear-Threshold          12      integer         Acc
+ATTRIBUTE      Acc-ML-Damping-Factor           13      integer         Acc
+ATTRIBUTE      Acc-Tunnel-Secret               14      string          Acc
+ATTRIBUTE      Acc-Clearing-Cause              15      integer         Acc
+ATTRIBUTE      Acc-Clearing-Location           16      integer         Acc
+ATTRIBUTE      Acc-Service-Profile             17      string          Acc
+ATTRIBUTE      Acc-Request-Type                18      integer         Acc
+ATTRIBUTE      Acc-Bridging-Support            19      integer         Acc
+ATTRIBUTE      Acc-Apsm-Oversubscribed         20      integer         Acc
+ATTRIBUTE      Acc-Acct-On-Off-Reason          21      integer         Acc
+ATTRIBUTE      Acc-Tunnel-Port                 22      integer         Acc
+ATTRIBUTE      Acc-Dns-Server-Pri              23      ipaddr          Acc
+ATTRIBUTE      Acc-Dns-Server-Sec              24      ipaddr          Acc
+ATTRIBUTE      Acc-Nbns-Server-Pri             25      ipaddr          Acc
+ATTRIBUTE      Acc-Nbns-Server-Sec             26      ipaddr          Acc
+ATTRIBUTE      Acc-Dial-Port-Index             27      integer         Acc
+ATTRIBUTE      Acc-Ip-Compression              28      integer         Acc
+ATTRIBUTE      Acc-Ipx-Compression             29      integer         Acc
+ATTRIBUTE      Acc-Connect-Tx-Speed            30      integer         Acc
+ATTRIBUTE      Acc-Connect-Rx-Speed            31      integer         Acc
+ATTRIBUTE      Acc-Modem-Modulation-Type       32      string          Acc
+ATTRIBUTE      Acc-Modem-Error-Protocol        33      string          Acc
+ATTRIBUTE      Acc-Callback-Delay              34      integer         Acc
+ATTRIBUTE      Acc-Callback-Num-Valid          35      string          Acc
+ATTRIBUTE      Acc-Callback-Mode               36      integer         Acc
+ATTRIBUTE      Acc-Callback-CBCP-Type          37      integer         Acc
+ATTRIBUTE      Acc-Dialout-Auth-Mode           38      integer         Acc
+ATTRIBUTE      Acc-Dialout-Auth-Password       39      string          Acc
+ATTRIBUTE      Acc-Dialout-Auth-Username       40      string          Acc
+ATTRIBUTE      Acc-Access-Community            42      integer         Acc
+
+VALUE          Acc-Reason-Code         No-reason-No-Failure            0
+VALUE          Acc-Reason-Code         Resource-shortage               1
+VALUE          Acc-Reason-Code         Session-already-open            2
+VALUE          Acc-Reason-Code         Too-many-RADIUS-users           3
+VALUE          Acc-Reason-Code         No-authentification-server      4
+VALUE          Acc-Reason-Code         No-authentification-response    5
+VALUE          Acc-Reason-Code         No-accounting-server            6
+VALUE          Acc-Reason-Code         No-accounting-response          7
+VALUE          Acc-Reason-Code         Access-Denied                   8
+VALUE          Acc-Reason-Code         Temporary-buffer-shortage       9
+VALUE          Acc-Reason-Code         Protocol-error                  10
+VALUE          Acc-Reason-Code         Invalid-attribute               11
+VALUE          Acc-Reason-Code         Invalid-service-type            12
+VALUE          Acc-Reason-Code         Invalid-framed-protocol         13
+VALUE          Acc-Reason-Code         Invalid-attribute-value         14
+VALUE          Acc-Reason-Code         Invalid-user-information        15
+VALUE          Acc-Reason-Code         Invalid-IP-address              16
+VALUE          Acc-Reason-Code         Invalid-integer-syntax          17
+VALUE          Acc-Reason-Code         Invalid-NAS-port                18
+VALUE          Acc-Reason-Code         Requested-by-user               19
+VALUE          Acc-Reason-Code         Network-disconnect              20
+VALUE          Acc-Reason-Code         Service-interruption            21
+VALUE          Acc-Reason-Code         Physical-port-error             22
+VALUE          Acc-Reason-Code         Idle-timeout                    23
+VALUE          Acc-Reason-Code         Session-timeout                 24
+VALUE          Acc-Reason-Code         Administrative-reset            25
+VALUE          Acc-Reason-Code         NAS-reload-or-reset             26
+VALUE          Acc-Reason-Code         NAS-error                       27
+VALUE          Acc-Reason-Code         NAS-request                     28
+VALUE          Acc-Reason-Code         Undefined-reason-given          29
+VALUE          Acc-Reason-Code         Conflicting-attributes          30
+VALUE          Acc-Reason-Code         Port-limit-exceeded             31
+VALUE          Acc-Reason-Code         Facility-not-available          32
+VALUE          Acc-Reason-Code         Internal-config-error           33
+VALUE          Acc-Reason-Code         Bad-route-specification         34
+VALUE          Acc-Reason-Code         Access-Partition-bind-failure   35
+VALUE          Acc-Reason-Code         Security-violation              36
+VALUE          Acc-Reason-Code         Request-type-conflict           37
+VALUE          Acc-Reason-Code         Configuration-disallowed        38
+VALUE          Acc-Reason-Code         Missing-attribute               39
+VALUE          Acc-Reason-Code         Invalid-request                 40
+VALUE          Acc-Reason-Code         Missing-parameter               41
+VALUE          Acc-Reason-Code         Invalid-parameter               42
+VALUE          Acc-Reason-Code         Call-cleared-with-cause         43
+VALUE          Acc-Reason-Code         Inopportune-config-request      44
+VALUE          Acc-Reason-Code         Invalid-config-parameter        45
+VALUE          Acc-Reason-Code         Missing-config-parameter        46
+VALUE          Acc-Reason-Code         Incompatible-service-profile    47
+VALUE          Acc-Reason-Code         Administrative-reset            48
+VALUE          Acc-Reason-Code         Administrative-reload           49
+VALUE          Acc-Reason-Code         Port-unneeded                   50
+VALUE          Acc-Reason-Code         Port-preempted                  51
+VALUE          Acc-Reason-Code         Port-suspended                  52
+VALUE          Acc-Reason-Code         Service-unavailable             53
+VALUE          Acc-Reason-Code         Callback                        54
+VALUE          Acc-Reason-Code         User-error                      55
+VALUE          Acc-Reason-Code         Host-request                    56
+
+VALUE          Acc-Ccp-Option          Disabled                        1
+VALUE          Acc-Ccp-Option          Enabled                         2
+
+VALUE          Acc-Route-Policy        Funnel                          1
+VALUE          Acc-Route-Policy        Direct                          2
+
+VALUE          Acc-ML-MLX-Admin-State  Enabled                         1
+VALUE          Acc-ML-MLX-Admin-State  Disabled                        2
+
+VALUE          Acc-Clearing-Cause      Cause-unspecified               0
+VALUE          Acc-Clearing-Cause      Unassigned-number               1
+VALUE          Acc-Clearing-Cause      No-route-to-transit-network     2
+VALUE          Acc-Clearing-Cause      No-route-to-destination         3
+VALUE          Acc-Clearing-Cause      Channel-unacceptable            6
+VALUE          Acc-Clearing-Cause      Call-awarded-being-delivered    7
+VALUE          Acc-Clearing-Cause      Normal-clearing                 16
+VALUE          Acc-Clearing-Cause      User-busy                       17
+VALUE          Acc-Clearing-Cause      No-user-responding              18
+VALUE          Acc-Clearing-Cause      User-alerted-no-answer          19
+VALUE          Acc-Clearing-Cause      Call-rejected                   21
+VALUE          Acc-Clearing-Cause      Number-changed                  22
+VALUE          Acc-Clearing-Cause      Non-selected-user-clearing      26
+VALUE          Acc-Clearing-Cause      Destination-out-of-order        27
+VALUE          Acc-Clearing-Cause      Invalid-or-incomplete-number    28
+VALUE          Acc-Clearing-Cause      Facility-rejected               29
+VALUE          Acc-Clearing-Cause      Response-to-status-inquiry      30
+VALUE          Acc-Clearing-Cause      Normal-unspecified-cause        31
+VALUE          Acc-Clearing-Cause      No-circuit-or-channel-available 34
+VALUE          Acc-Clearing-Cause      Network-out-of-order            38
+VALUE          Acc-Clearing-Cause      Temporary-failure               41
+VALUE          Acc-Clearing-Cause      Switching-equipment-congestion  42
+VALUE          Acc-Clearing-Cause      Access-information-discarded    43
+VALUE          Acc-Clearing-Cause      Circuit-or-channel-unavailable  44
+VALUE          Acc-Clearing-Cause      Circuit-or-channed-preempted    45
+VALUE          Acc-Clearing-Cause      Resources-unavailable           47
+VALUE          Acc-Clearing-Cause      Quality-of-service-unavailable  49
+VALUE          Acc-Clearing-Cause      Facility-not-subscribed         50
+VALUE          Acc-Clearing-Cause      Outgoing-calls-barred           52
+VALUE          Acc-Clearing-Cause      Incoming-calls-barred           54
+VALUE          Acc-Clearing-Cause      Bearer-capability-unauthorized  57
+VALUE          Acc-Clearing-Cause      Bearer-capability-not-available 58
+VALUE          Acc-Clearing-Cause      Service-not-available           63
+VALUE          Acc-Clearing-Cause      Bearer-capablity-not-implmented 65
+VALUE          Acc-Clearing-Cause      Channel-type-not-implemented    66
+VALUE          Acc-Clearing-Cause      Facility-not-implemented        69
+VALUE          Acc-Clearing-Cause      Restrcted-digtal-infrmtion-only 70
+VALUE          Acc-Clearing-Cause      Service-not-implemented         79
+VALUE          Acc-Clearing-Cause      Invalid-call-reference          81
+VALUE          Acc-Clearing-Cause      Identified-channel-doesnt-exist 82
+VALUE          Acc-Clearing-Cause      Call-identify-in-use            84
+VALUE          Acc-Clearing-Cause      No-call-suspended               85
+VALUE          Acc-Clearing-Cause      Suspended-call-cleared          86
+VALUE          Acc-Clearing-Cause      Incompatible-destination        88
+VALUE          Acc-Clearing-Cause      Invalid-transit-network-selctin 91
+VALUE          Acc-Clearing-Cause      Invalid-message                 95
+VALUE          Acc-Clearing-Cause      Mandtory-infrmtion-elment-miss  96
+VALUE          Acc-Clearing-Cause      Message-not-implemented         97
+VALUE          Acc-Clearing-Cause      Inopportune-message             98
+VALUE          Acc-Clearing-Cause      Infrmtion-elemnt-not-implmented 99
+VALUE          Acc-Clearing-Cause      Invlid-infrmtion-element-contnt 100
+VALUE          Acc-Clearing-Cause      Message-incompatible-with-state 101
+VALUE          Acc-Clearing-Cause      Recovery-on-timer-expiration    102
+VALUE          Acc-Clearing-Cause      Mndtry-infrmtion-elmnt-lngt-err 103
+VALUE          Acc-Clearing-Cause      Protocol-error                  111
+VALUE          Acc-Clearing-Cause      Interworking                    127
+
+VALUE          Acc-Clearing-Location   Local-or-remote-user            0
+VALUE          Acc-Clearing-Location   Prvte-ntwork-serving-local-user 1
+VALUE          Acc-Clearing-Location   Pblic-ntwork-serving-local-user 2
+VALUE          Acc-Clearing-Location   Transit-network                 3
+VALUE          Acc-Clearing-Location   Prvte-ntwork-serv-remote-user   4
+VALUE          Acc-Clearing-Location   Pblic-ntwork-serv-remote-user   5
+VALUE          Acc-Clearing-Location   International-network           6
+VALUE          Acc-Clearing-Location   Beyond-interworking-point       10
+
+VALUE          Acc-Request-Type        Ring-Indication                 1
+VALUE          Acc-Request-Type        Dial-Request                    2
+VALUE          Acc-Request-Type        User-Authentification           3
+VALUE          Acc-Request-Type        Tunnel-Authentification         4
+
+VALUE          Acc-Bridging-Support    Disabled                        1
+VALUE          Acc-Bridging-Support    Enabled                         2
+
+VALUE          Acc-Apsm-Oversubscribed False                           1
+VALUE          Acc-Apsm-Oversubscribed True                            2
+
+VALUE          Acc-Acct-On-Off-Reason  NAS-Reset                       0
+VALUE          Acc-Acct-On-Off-Reason  NAS-Reload                      1
+VALUE          Acc-Acct-On-Off-Reason  Configuration-Reset             2
+VALUE          Acc-Acct-On-Off-Reason  Configuration-Reload            3
+VALUE          Acc-Acct-On-Off-Reason  Enabled                         4
+VALUE          Acc-Acct-On-Off-Reason  Disabled                        5
+
+VALUE          Acc-Ip-Compression      Disabled                        1
+VALUE          Acc-Ip-Compression      Enabled                         2
+
+VALUE          Acc-Ipx-Compression     Disabled                        1
+VALUE          Acc-Ipx-Compression     Enabled                         2
+
+VALUE          Acc-Callback-Mode       User-Auth                       0
+VALUE          Acc-Callback-Mode       User-Specified-E-164            3
+VALUE          Acc-Callback-Mode       CBCP-Callback                   6
+VALUE          Acc-Callback-Mode       CLI-Callback                    7
+
+VALUE          Acc-Callback-CBCP-Type  CBCP-None                       1
+VALUE          Acc-Callback-CBCP-Type  CBCP-User-Specified             2
+VALUE          Acc-Callback-CBCP-Type  CBCP-Pre-Specified              3
+
+VALUE          Acc-Dialout-Auth-Mode   PAP                             1
+VALUE          Acc-Dialout-Auth-Mode   CHAP                            2
+VALUE          Acc-Dialout-Auth-Mode   CHAP-PAP                        3
+VALUE          Acc-Dialout-Auth-Mode   NONE                            4
+
+VALUE          Acc-Access-Community    PUBLIC                          1
+VALUE          Acc-Access-Community    NETMAN                          2
+
diff --git a/share/dictionary.ascend b/share/dictionary.ascend
new file mode 100644 (file)
index 0000000..ea55e14
--- /dev/null
@@ -0,0 +1,300 @@
+#
+# Ascend dictionary.
+#
+#              Enable by putting the line "$INCLUDE dictionary.ascend" into
+#              the main dictionary file.
+#
+# Version:     1.00  21-Jul-1997  Jens Glaser <jens@regio.net>
+#              1.01  22-Jan-1998  Tomas Pospisek <tpo@spin.ch>
+#
+
+
+#
+#      Ascend specific extensions
+#      Used by ASCEND MAX/Pipeline products
+#
+ATTRIBUTE      Ascend-FCP-Parameter            119     string
+ATTRIBUTE      Ascend-Modem-PortNo             120     integer
+ATTRIBUTE      Ascend-Modem-SlotNo             121     integer
+ATTRIBUTE      Ascend-Modem-ShelfNo            122     integer
+ATTRIBUTE      Ascend-Call-Attempt-Limit       123     integer
+ATTRIBUTE      Ascend-Call-Block-Duration      124     integer
+ATTRIBUTE      Ascend-Maximum-Call-Duration    125     integer
+ATTRIBUTE      Ascend-Temporary-Rtes           126     integer
+ATTRIBUTE       Tunneling-Protocol              127     integer
+ATTRIBUTE       Ascend-Shared-Profile-Enable    128     integer
+ATTRIBUTE      Ascend-Primary-Home-Agent       129     string
+ATTRIBUTE      Ascend-Secondary-Home-Agent     130     string
+ATTRIBUTE      Ascend-Dialout-Allowed          131     integer
+ATTRIBUTE      Ascend-Client-Gateway           132     ipaddr
+ATTRIBUTE      Ascend-BACP-Enable              133     integer
+ATTRIBUTE      Ascend-DHCP-Maximum-Leases      134     integer
+ATTRIBUTE      Ascend-Client-Primary-DNS       135     ipaddr
+ATTRIBUTE      Ascend-Client-Secondary-DNS     136     ipaddr
+ATTRIBUTE      Ascend-Client-Assign-DNS        137     integer
+ATTRIBUTE      Ascend-User-Acct-Type           138     integer
+ATTRIBUTE      Ascend-User-Acct-Host           139     ipaddr
+ATTRIBUTE      Ascend-User-Acct-Port           140     integer
+ATTRIBUTE      Ascend-User-Acct-Key            141     string
+ATTRIBUTE      Ascend-User-Acct-Base           142     integer
+ATTRIBUTE      Ascend-User-Acct-Time           143     integer
+ATTRIBUTE      Ascend-Assign-IP-Client         144     ipaddr
+ATTRIBUTE      Ascend-Assign-IP-Server         145     ipaddr
+ATTRIBUTE      Ascend-Assign-IP-Global-Pool    146     string
+ATTRIBUTE      Ascend-DHCP-Reply               147     integer
+ATTRIBUTE      Ascend-DHCP-Pool-Number         148     integer
+ATTRIBUTE      Ascend-Expect-Callback          149     integer
+ATTRIBUTE      Ascend-Event-Type               150     integer
+ATTRIBUTE      Ascend-Session-Svr-Key          151     string
+ATTRIBUTE      Ascend-Multicast-Rate-Limit     152     integer
+ATTRIBUTE      Ascend-IF-Netmask               153     ipaddr
+ATTRIBUTE      Ascend-Remote-Addr              154     ipaddr
+ATTRIBUTE      Ascend-Multicast-Client         155     integer
+ATTRIBUTE      Ascend-FR-Circuit-Name          156     string
+ATTRIBUTE      Ascend-FR-LinkUp                157     integer
+ATTRIBUTE      Ascend-FR-Nailed-Grp            158     integer
+ATTRIBUTE      Ascend-FR-Type                  159     integer
+ATTRIBUTE      Ascend-FR-Link-Mgt              160     integer
+ATTRIBUTE      Ascend-FR-N391                  161     integer
+ATTRIBUTE      Ascend-FR-DCE-N392              162     integer
+ATTRIBUTE      Ascend-FR-DTE-N392              163     integer
+ATTRIBUTE      Ascend-FR-DCE-N393              164     integer
+ATTRIBUTE      Ascend-FR-DTE-N393              165     integer
+ATTRIBUTE      Ascend-FR-T391                  166     integer
+ATTRIBUTE      Ascend-FR-T392                  167     integer
+ATTRIBUTE      Ascend-Bridge-Address           168     string
+ATTRIBUTE       Ascend-TS-Idle-Limit            169     integer
+ATTRIBUTE       Ascend-TS-Idle-Mode             170     integer
+ATTRIBUTE      Ascend-DBA-Monitor              171     integer
+ATTRIBUTE      Ascend-Base-Channel-Count       172     integer
+ATTRIBUTE      Ascend-Minimum-Channels         173     integer
+ATTRIBUTE      Ascend-IPX-Route                174     string
+ATTRIBUTE      Ascend-FT1-Caller               175     integer
+ATTRIBUTE      Ascend-Backup                   176     string
+ATTRIBUTE      Ascend-Call-Type                177     integer
+ATTRIBUTE      Ascend-Group                    178     string
+ATTRIBUTE      Ascend-FR-DLCI                  179     integer
+ATTRIBUTE      Ascend-FR-Profile-Name          180     string
+ATTRIBUTE      Ascend-Ara-PW                   181     string
+ATTRIBUTE      Ascend-IPX-Node-Addr            182     string
+ATTRIBUTE      Ascend-Home-Agent-IP-Addr       183     ipaddr
+ATTRIBUTE      Ascend-Home-Agent-Password      184     string
+ATTRIBUTE      Ascend-Home-Network-Name        185     string
+ATTRIBUTE      Ascend-Home-Agent-UDP-Port      186     integer
+ATTRIBUTE      Ascend-Multilink-ID             187     integer
+ATTRIBUTE      Ascend-Num-In-Multilink         188     integer
+ATTRIBUTE      Ascend-First-Dest               189     ipaddr
+ATTRIBUTE      Ascend-Pre-Input-Octets         190     integer
+ATTRIBUTE      Ascend-Pre-Output-Octets        191     integer
+ATTRIBUTE      Ascend-Pre-Input-Packets        192     integer
+ATTRIBUTE      Ascend-Pre-Output-Packets       193     integer
+ATTRIBUTE      Ascend-Maximum-Time             194     integer
+ATTRIBUTE      Ascend-Disconnect-Cause         195     integer
+ATTRIBUTE      Ascend-Connect-Progress         196     integer
+ATTRIBUTE      Ascend-Data-Rate                197     integer
+ATTRIBUTE      Ascend-PreSession-Time          198     integer
+ATTRIBUTE      Ascend-Token-Idle               199     integer
+ATTRIBUTE      Ascend-Token-Immediate          200     integer
+ATTRIBUTE      Ascend-Require-Auth             201     integer
+ATTRIBUTE      Ascend-Number-Sessions          202     string
+ATTRIBUTE      Ascend-Authen-Alias             203     string
+ATTRIBUTE      Ascend-Token-Expiry             204     integer
+ATTRIBUTE      Ascend-Menu-Selector            205     string
+ATTRIBUTE      Ascend-Menu-Item                206     string
+ATTRIBUTE      Ascend-PW-Warntime              207     integer
+ATTRIBUTE      Ascend-PW-Lifetime              208     integer
+ATTRIBUTE      Ascend-IP-Direct                209     ipaddr
+ATTRIBUTE      Ascend-PPP-VJ-Slot-Comp         210     integer
+ATTRIBUTE      Ascend-PPP-VJ-1172              211     integer
+ATTRIBUTE      Ascend-PPP-Async-Map            212     integer
+ATTRIBUTE      Ascend-Third-Prompt             213     string
+ATTRIBUTE      Ascend-Send-Secret              214     string
+ATTRIBUTE      Ascend-Receive-Secret           215     string
+ATTRIBUTE      Ascend-IPX-Peer-Mode            216     integer
+ATTRIBUTE      Ascend-IP-Pool-Definition       217     string
+ATTRIBUTE      Ascend-Assign-IP-Pool           218     integer
+ATTRIBUTE      Ascend-FR-Direct                219     integer
+ATTRIBUTE      Ascend-FR-Direct-Profile        220     string
+ATTRIBUTE      Ascend-FR-Direct-DLCI           221     integer
+ATTRIBUTE      Ascend-Handle-IPX               222     integer
+ATTRIBUTE      Ascend-Netware-timeout          223     integer
+ATTRIBUTE      Ascend-IPX-Alias                224     integer
+ATTRIBUTE      Ascend-Metric                   225     integer
+ATTRIBUTE      Ascend-PRI-Number-Type          226     integer
+ATTRIBUTE      Ascend-Dial-Number              227     string
+ATTRIBUTE      Ascend-Route-IP                 228     integer
+ATTRIBUTE      Ascend-Route-IPX                229     integer
+ATTRIBUTE      Ascend-Bridge                   230     integer
+ATTRIBUTE      Ascend-Send-Auth                231     integer
+ATTRIBUTE      Ascend-Send-Passwd              232     string
+ATTRIBUTE      Ascend-Link-Compression         233     integer
+ATTRIBUTE      Ascend-Target-Util              234     integer
+ATTRIBUTE      Ascend-Maximum-Channels         235     integer
+ATTRIBUTE      Ascend-Inc-Channel-Count        236     integer
+ATTRIBUTE      Ascend-Dec-Channel-Count        237     integer
+ATTRIBUTE      Ascend-Seconds-Of-History       238     integer
+ATTRIBUTE      Ascend-History-Weigh-Type       239     integer
+ATTRIBUTE      Ascend-Add-Seconds              240     integer
+ATTRIBUTE      Ascend-Remove-Seconds           241     integer
+ATTRIBUTE      Ascend-Idle-Limit               244     integer
+ATTRIBUTE      Ascend-Preempt-Limit            245     integer
+ATTRIBUTE      Ascend-Callback                 246     integer
+ATTRIBUTE      Ascend-Data-Svc                 247     integer
+ATTRIBUTE      Ascend-Force-56                 248     integer
+ATTRIBUTE      Ascend-Billing-Number           249     string
+ATTRIBUTE      Ascend-Call-By-Call             250     integer
+ATTRIBUTE      Ascend-Transit-Number           251     string
+ATTRIBUTE      Ascend-Host-Info                252     string
+ATTRIBUTE      Ascend-PPP-Address              253     ipaddr
+ATTRIBUTE      Ascend-MPP-Idle-Percent         254     integer
+ATTRIBUTE      Ascend-Xmit-Rate                255     integer
+
+
+
+# Ascend protocols
+VALUE          Service-Type            Dialout-Framed-User     5
+VALUE          Framed-Protocol         ARA                     255
+VALUE          Framed-Protocol         MPP                     256
+VALUE          Framed-Protocol         EURAW                   257
+VALUE          Framed-Protocol         EUUI                    258
+VALUE          Framed-Protocol         X25                     259
+VALUE          Framed-Protocol         COMB                    260
+VALUE          Framed-Protocol         FR                      261
+VALUE          Framed-Protocol         MP                      262
+VALUE          Framed-Protocol         FR-CIR                  263
+
+
+#
+#      Ascend specific extensions
+#      Used by ASCEND MAX/Pipeline products (see above)
+#
+
+VALUE          Ascend-FR-Direct        FR-Direct-No            0
+VALUE          Ascend-FR-Direct        FR-Direct-Yes           1
+VALUE          Ascend-Handle-IPX       Handle-IPX-None         0
+VALUE          Ascend-Handle-IPX       Handle-IPX-Client       1
+VALUE          Ascend-Handle-IPX       Handle-IPX-Server       2
+VALUE          Ascend-IPX-Peer-Mode    IPX-Peer-Router         0
+VALUE          Ascend-IPX-Peer-Mode    IPX-Peer-Dialin         1
+VALUE          Ascend-Call-Type        Nailed                  1
+VALUE          Ascend-Call-Type        Nailed/Mpp              2
+VALUE          Ascend-Call-Type        Perm/Switched           3
+VALUE          Ascend-FT1-Caller       FT1-No                  0
+VALUE          Ascend-FT1-Caller       FT1-Yes                 1
+VALUE          Ascend-PRI-Number-Type  Unknown-Number          0
+VALUE          Ascend-PRI-Number-Type  Intl-Number             1
+VALUE          Ascend-PRI-Number-Type  National-Number         2
+VALUE          Ascend-PRI-Number-Type  Local-Number            4
+VALUE          Ascend-PRI-Number-Type  Abbrev-Number           5
+VALUE          Ascend-Route-IP         Route-IP-No             0
+VALUE          Ascend-Route-IP         Route-IP-Yes            1
+VALUE          Ascend-Route-IPX        Route-IPX-No            0
+VALUE          Ascend-Route-IPX        Route-IPX-Yes           1
+VALUE          Ascend-Bridge           Bridge-No               0
+VALUE          Ascend-Bridge           Bridge-Yes              1
+VALUE                  Ascend-TS-Idle-Mode     TS-Idle-None            0
+VALUE          Ascend-TS-Idle-Mode     TS-Idle-Input           1
+VALUE                  Ascend-TS-Idle-Mode     TS-Idle-Input-Output    2
+VALUE          Ascend-Send-Auth        Send-Auth-None          0
+VALUE          Ascend-Send-Auth        Send-Auth-PAP           1
+VALUE          Ascend-Send-Auth        Send-Auth-CHAP          2
+VALUE          Ascend-Send-Auth        Send-Auth-MS-CHAP       3
+VALUE          Ascend-Link-Compression Link-Comp-None          0
+VALUE          Ascend-Link-Compression Link-Comp-Stac          1
+VALUE          Ascend-Link-Compression Link-Comp-Stac-Draft-9  2
+VALUE          Ascend-Link-Compression Link-Comp-MS-Stac       3
+VALUE          Ascend-History-Weigh-Type       History-Constant        0
+VALUE          Ascend-History-Weigh-Type       History-Linear          1
+VALUE          Ascend-History-Weigh-Type       History-Quadratic       2
+VALUE          Ascend-Callback         Callback-No             0
+VALUE          Ascend-Callback         Callback-Yes            1
+VALUE          Ascend-Expect-Callback  Expect-Callback-No      0
+VALUE          Ascend-Expect-Callback  Expect-Callback-Yes     1
+VALUE          Ascend-Data-Svc         Switched-Voice-Bearer   0
+VALUE          Ascend-Data-Svc         Switched-56KR           1
+VALUE          Ascend-Data-Svc         Switched-64K            2
+VALUE          Ascend-Data-Svc         Switched-64KR           3
+VALUE          Ascend-Data-Svc         Switched-56K            4
+VALUE          Ascend-Data-Svc         Switched-384KR          5
+VALUE          Ascend-Data-Svc         Switched-384K           6
+VALUE          Ascend-Data-Svc         Switched-1536K          7
+VALUE          Ascend-Data-Svc         Switched-1536KR         8
+VALUE          Ascend-Data-Svc         Switched-128K           9
+VALUE          Ascend-Data-Svc         Switched-192K           10
+VALUE          Ascend-Data-Svc         Switched-256K           11
+VALUE          Ascend-Data-Svc         Switched-320K           12
+VALUE          Ascend-Data-Svc         Switched-384K-MR        13
+VALUE          Ascend-Data-Svc         Switched-448K           14
+VALUE          Ascend-Data-Svc         Switched-512K           15
+VALUE          Ascend-Data-Svc         Switched-576K           16
+VALUE          Ascend-Data-Svc         Switched-640K           17
+VALUE          Ascend-Data-Svc         Switched-704K           18
+VALUE          Ascend-Data-Svc         Switched-768K           19
+VALUE          Ascend-Data-Svc         Switched-832K           20
+VALUE          Ascend-Data-Svc         Switched-896K           21
+VALUE          Ascend-Data-Svc         Switched-960K           22
+VALUE          Ascend-Data-Svc         Switched-1024K          23
+VALUE          Ascend-Data-Svc         Switched-1088K          24
+VALUE          Ascend-Data-Svc         Switched-1152K          25
+VALUE          Ascend-Data-Svc         Switched-1216K          26
+VALUE          Ascend-Data-Svc         Switched-1280K          27
+VALUE          Ascend-Data-Svc         Switched-1344K          28
+VALUE          Ascend-Data-Svc         Switched-1408K          29
+VALUE          Ascend-Data-Svc         Switched-1472K          30
+VALUE          Ascend-Data-Svc         Switched-1600K          31
+VALUE          Ascend-Data-Svc         Switched-1664K          32
+VALUE          Ascend-Data-Svc         Switched-1728K          33
+VALUE          Ascend-Data-Svc         Switched-1792K          34
+VALUE          Ascend-Data-Svc         Switched-1856K          35
+VALUE          Ascend-Data-Svc         Switched-1920K          36
+VALUE          Ascend-Data-Svc         Switched-inherited              37
+VALUE          Ascend-Data-Svc         Switched-restricted-bearer-x30  38
+VALUE          Ascend-Data-Svc         Switched-clear-bearer-v110      39
+VALUE          Ascend-Data-Svc         Switched-restricted-64-x30      40
+VALUE          Ascend-Data-Svc         Switched-clear-56-v110          41
+VALUE          Ascend-Data-Svc         Switched-modem                  42
+VALUE          Ascend-Data-Svc         Switched-atmodem                43
+VALUE          Ascend-Data-Svc         Nailed-56KR             1
+VALUE          Ascend-Data-Svc         Nailed-64K              2
+VALUE          Ascend-Force-56         Force-56-No             0
+VALUE          Ascend-Force-56         Force-56-Yes            1
+VALUE          Ascend-PW-Lifetime      Lifetime-In-Days        0
+VALUE          Ascend-PW-Warntime      Days-Of-Warning         0
+VALUE          Ascend-PPP-VJ-1172      PPP-VJ-1172             1
+VALUE          Ascend-PPP-VJ-Slot-Comp VJ-Slot-Comp-No         1
+VALUE          Ascend-Require-Auth     Not-Require-Auth        0
+VALUE          Ascend-Require-Auth     Require-Auth            1
+VALUE          Ascend-Token-Immediate  Tok-Imm-No              0
+VALUE          Ascend-Token-Immediate  Tok-Imm-Yes             1
+VALUE          Ascend-DBA-Monitor              DBA-Transmit            0
+VALUE          Ascend-DBA-Monitor      DBA-Transmit-Recv       1
+VALUE          Ascend-DBA-Monitor      DBA-None                2
+VALUE          Ascend-FR-Type          Ascend-FR-DTE           0
+VALUE          Ascend-FR-Type          Ascend-FR-DCE           1
+VALUE          Ascend-FR-Type          Ascend-FR-NNI           2
+VALUE          Ascend-FR-Link-Mgt      Ascend-FR-No-Link-Mgt   0
+VALUE          Ascend-FR-Link-Mgt      Ascend-FR-T1-617D       1
+VALUE          Ascend-FR-Link-Mgt      Ascend-FR-Q-933A        2
+VALUE          Ascend-FR-LinkUp        Ascend-LinkUp-Default   0
+VALUE          Ascend-FR-LinkUp        Ascend-LinkUp-AlwaysUp  1
+VALUE          Ascend-Multicast-Client Multicast-No            0
+VALUE          Ascend-Multicast-Client Multicast-Yes           1
+VALUE          Ascend-User-Acct-Type   Ascend-User-Acct-None   0
+VALUE          Ascend-User-Acct-Type   Ascend-User-Acct-User   1
+VALUE          Ascend-User-Acct-Type   Ascend-User-Acct-User-Default   2
+VALUE          Ascend-User-Acct-Base   Base-10                 0
+VALUE          Ascend-User-Acct-Base   Base-16                 1
+VALUE          Ascend-DHCP-Reply       DHCP-Reply-No           0
+VALUE          Ascend-DHCP-Reply       DHCP-Reply-Yes          1
+VALUE          Ascend-Client-Assign-DNS        DNS-Assign-No           0
+VALUE          Ascend-Client-Assign-DNS        DNS-Assign-Yes          1
+VALUE          Ascend-Event-Type       Ascend-ColdStart        1
+VALUE          Ascend-Event-Type       Ascend-Session-Event    2
+VALUE          Ascend-BACP-Enable      BACP-No                 0
+VALUE          Ascend-BACP-Enable      BACP-Yes                1
+VALUE          Ascend-Dialout-Allowed  Dialout-Not-Allowed     0
+VALUE          Ascend-Dialout-Allowed  Dialout-Allowed         1
+VALUE          Ascend-Shared-Profile-Enable    Shared-Profile-No       0
+VALUE          Ascend-Shared-Profile-Enable    Shared-Profile-Yes      1
+VALUE          Ascend-Temporary-Rtes   Temp-Rtes-No            0
+VALUE          Ascend-Temporary-Rtes   Temp-Rtes-Yes           1
diff --git a/share/dictionary.cisco b/share/dictionary.cisco
new file mode 100644 (file)
index 0000000..9e840f7
--- /dev/null
@@ -0,0 +1,71 @@
+#
+# dictionary.cisco
+#
+#              Accounting VSAs by
+#              "Marcelo M. Sosa Lugones" <marcelo@sosa.com.ar>
+#
+# Version:     @(#)dictionary.cisco  1.01  21-Mar-1999  miquels@cistron.nl
+#
+
+VENDOR         Cisco           9
+
+#
+#      Standard attribute
+#
+ATTRIBUTE      Cisco-AVPair    1       string          Cisco
+
+#
+#      Extra attributes sent by the Cisco, if you configure
+#      "radius-server vsa accounting" (requires IOS11.2+).
+#
+ATTRIBUTE       Cisco-Multilink-ID              187     integer                Cisco
+ATTRIBUTE       Cisco-Num-In-Multilink          188     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Input-Octets          190     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Output-Octets         191     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Input-Packets         192     integer                Cisco
+ATTRIBUTE       Cisco-Pre-Output-Packets        193     integer                Cisco
+ATTRIBUTE       Cisco-Maximun-Time              194     integer                Cisco
+ATTRIBUTE       Cisco-Disconnect-Cause          195     integer                Cisco
+ATTRIBUTE       Cisco-Data-Rate                 197     integer                Cisco
+ATTRIBUTE       Cisco-PreSession-Time           198     integer                Cisco
+ATTRIBUTE       Cisco-PW-Lifetime               208     integer                Cisco
+ATTRIBUTE       Cisco-IP-Direct                 209     integer                Cisco
+ATTRIBUTE       Cisco-PPP-VJ-Slot-Comp          210     integer                Cisco
+ATTRIBUTE       Cisco-PPP-Async-Map             212     integer                Cisco
+ATTRIBUTE       Cisco-IP-Pool-Definition        217     integer                Cisco
+ATTRIBUTE       Cisco-Asing-IP-Pool             218     integer                Cisco
+ATTRIBUTE       Cisco-Route-IP                  228     integer                Cisco
+ATTRIBUTE       Cisco-Link-Compression          233     integer                Cisco
+ATTRIBUTE       Cisco-Target-Util               234     integer                Cisco
+ATTRIBUTE       Cisco-Maximun-Channels          235     integer                Cisco
+ATTRIBUTE       Cisco-Data-Filter               242     integer                Cisco
+ATTRIBUTE       Cisco-Call-Filter               243     integer                Cisco
+ATTRIBUTE       Cisco-Idle-Limit                244     integer                Cisco
+ATTRIBUTE       Cisco-Xmit-Rate                 255     integer                Cisco
+
+VALUE           Cisco-Disconnect-Cause        Unknown                 2
+VALUE           Cisco-Disconnect-Cause        CLID-Authentication-Failure     4
+VALUE           Cisco-Disconnect-Cause        No-Carrier              10
+VALUE           Cisco-Disconnect-Cause        Lost-Carrier            11
+VALUE           Cisco-Disconnect-Cause        No-Detected-Result-Codes        12
+VALUE           Cisco-Disconnect-Cause        User-Ends-Session       20
+VALUE           Cisco-Disconnect-Cause        Idle-Timeout            21
+VALUE           Cisco-Disconnect-Cause        Exit-Telnet-Session     22
+VALUE           Cisco-Disconnect-Cause        No-Remote-IP-Addr       23
+VALUE           Cisco-Disconnect-Cause        Exit-Raw-TCP            24
+VALUE           Cisco-Disconnect-Cause        Password-Fail           25
+VALUE           Cisco-Disconnect-Cause        Raw-TCP-Disabled        26
+VALUE           Cisco-Disconnect-Cause        Control-C-Detected      27
+VALUE           Cisco-Disconnect-Cause        EXEC-Program-Destroyed  28
+VALUE           Cisco-Disconnect-Cause        Timeout-PPP-LCP         40
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-LCP-Negotiation      41
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-PAP-Auth-Fail        42
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-CHAP-Auth    43
+VALUE           Cisco-Disconnect-Cause        Failed-PPP-Remote-Auth  44
+VALUE           Cisco-Disconnect-Cause        PPP-Remote-Terminate    45
+VALUE           Cisco-Disconnect-Cause        PPP-Closed-Event        46
+VALUE           Cisco-Disconnect-Cause        Session-Timeout         100
+VALUE           Cisco-Disconnect-Cause        Session-Failed-Security 101
+VALUE           Cisco-Disconnect-Cause        Session-End-Callback    102
+VALUE           Cisco-Disconnect-Cause        Invalid-Protocol        120
+
diff --git a/share/dictionary.compat b/share/dictionary.compat
new file mode 100644 (file)
index 0000000..4ffc7a3
--- /dev/null
@@ -0,0 +1,48 @@
+#
+#      Obsolete names for backwards compatibility with older users files.
+#      Move the $INCLUDE in the main dictionary file to the end if you want
+#      these names to be used in the "details" logfile.
+#
+ATTRIBUTE      Client-Id               4       ipaddr
+ATTRIBUTE      Client-Port-Id          5       integer
+ATTRIBUTE      User-Service-Type       6       integer
+ATTRIBUTE      Framed-Address          8       ipaddr
+ATTRIBUTE      Framed-Netmask          9       ipaddr
+ATTRIBUTE      Framed-Filter-Id        11      string
+ATTRIBUTE      Login-Host              14      ipaddr
+ATTRIBUTE      Login-Port              16      integer
+ATTRIBUTE      Old-Password            17      string
+ATTRIBUTE      Port-Message            18      string
+ATTRIBUTE      Dialback-No             19      string
+ATTRIBUTE      Dialback-Name           20      string
+ATTRIBUTE      Challenge-State         24      string
+VALUE          Framed-Compression      Van-Jacobsen-TCP-IP     1
+VALUE          Framed-Compression      VJ-TCP-IP               1
+VALUE          Service-Type            Shell-User              6
+VALUE          Auth-Type               Unix                    1
+VALUE          Service-Type            Dialback-Login-User     3
+VALUE          Service-Type            Dialback-Framed-User    4
+
+#
+#      For compatibility with MERIT users files.
+#
+ATTRIBUTE      NAS-Port                5       integer
+ATTRIBUTE      Login-Host              14      ipaddr
+ATTRIBUTE      Login-Callback-Number   19      string
+ATTRIBUTE      Framed-Callback-Id      20      string
+ATTRIBUTE      Client-Port-DNIS        30      string
+ATTRIBUTE      Caller-ID               31      string
+VALUE          Service-Type            Login                   1
+VALUE          Service-Type            Framed                  2
+VALUE          Service-Type            Callback-Login          3
+VALUE          Service-Type            Callback-Framed         4
+VALUE          Service-Type            Exec-User               7
+
+#
+#      For compatibility with ESVA RADIUS, Old Cistron RADIUS
+#
+ATTRIBUTE      Session                 1034    integer
+ATTRIBUTE      User-Name-Is-Star       1035    integer
+VALUE          User-Name-Is-Star       No                      0
+VALUE          User-Name-Is-Star       Yes                     1
+VALUE          Auth-Type               None                    254
diff --git a/share/dictionary.livingston b/share/dictionary.livingston
new file mode 100644 (file)
index 0000000..495abb5
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# Vendor-Specific attributes use the SMI Network Management Private
+# Enterprise Code from the "Assigned Numbers" RFC
+#
+VENDOR         Livingston      307
+
+#
+# Livingston Vendor-Specific Attributes (requires ComOS 3.8)
+#
+ATTRIBUTE      LE-Terminate-Detail     2       string  Livingston
+ATTRIBUTE      LE-Advice-of-Charge     3       string  Livingston
+
diff --git a/share/dictionary.shiva b/share/dictionary.shiva
new file mode 100644 (file)
index 0000000..b80ec6a
--- /dev/null
@@ -0,0 +1,86 @@
+#
+# Shiva dictionary.
+#
+#              Shiva Inc.
+#              http://www.shiva.com/
+#
+#              Enable by putting the line "$INCLUDE dictionary.shiva" into
+#              the main dictionary file.
+#
+# Version:     1.00  27-Apr-1999  contributed by Alan DeKok
+#
+
+VENDOR Shiva           166
+
+#      Shiva Extensions
+
+#
+#      ??? I don't know what this is, but it's "Acct-Link-Count"
+#      in the main dictionary.
+#
+#ATTRIBUTE     Shiva-User-Attributes           51      string
+
+ATTRIBUTE      Shiva-Called-Number             90      string Shiva
+ATTRIBUTE      Shiva-Calling-Number            91      string Shiva
+ATTRIBUTE      Shiva-Customer-Id               92      string Shiva
+ATTRIBUTE      Shiva-Type-Of-Service           93      integer Shiva
+ATTRIBUTE      Shiva-Link-Speed                94      integer Shiva
+ATTRIBUTE      Shiva-Links-In-Bundle           95      integer Shiva
+ATTRIBUTE      Shiva-Compression-Type          96      integer Shiva
+ATTRIBUTE      Shiva-Link-Protocol             97      integer Shiva
+ATTRIBUTE      Shiva-Network-Protocols         98      integer Shiva
+ATTRIBUTE      Shiva-Session-Id                99      integer Shiva
+ATTRIBUTE      Shiva-Disconnect-Reason         100     integer Shiva
+ATTRIBUTE      Shiva-Acct-Serv-Switch          101     ipaddr Shiva
+ATTRIBUTE      Shiva-Event-Flags               102     integer Shiva
+ATTRIBUTE      Shiva-Function                  103     integer Shiva
+ATTRIBUTE      Shiva-Connect-Reason            104     integer Shiva
+
+#      Shiva Type Of Service Values
+
+VALUE  Shiva-Type-Of-Service   Analog                  1
+VALUE  Shiva-Type-Of-Service   Digitized-Analog        2
+VALUE  Shiva-Type-Of-Service   Digital                 3
+VALUE  Shiva-Type-Of-Service   Digital-V110            4
+VALUE  Shiva-Type-Of-Service   Digital-V120            5
+VALUE  Shiva-Type-Of-Service   Digital-Leased-Line     6
+
+#      Shiva Link Protocol Values
+
+VALUE  Shiva-Link-Protocol     HDLC                    1
+VALUE  Shiva-Link-Protocol     ARAV1                   2
+VALUE  Shiva-Link-Protocol     ARAV2                   3
+VALUE  Shiva-Link-Protocol     SHELL                   4
+VALUE  Shiva-Link-Protocol     AALAP                   5
+VALUE  Shiva-Link-Protocol     SLIP                    6
+
+#      Shiva Connect Reason Values
+
+VALUE  Shiva-Connect-Reason    Remote                  1
+VALUE  Shiva-Connect-Reason    Dialback                2
+VALUE  Shiva-Connect-Reason    Virtual-Connection      3
+VALUE  Shiva-Connect-Reason    Bandwidth-On-Demand     4
+
+#      Shiva Disconnect Reason Values
+
+VALUE  Shiva-Disconnect-Reason Remote                  1
+VALUE  Shiva-Disconnect-Reason Error                   2
+VALUE  Shiva-Disconnect-Reason Idle-Timeout            3
+VALUE  Shiva-Disconnect-Reason Session-Timeout         4
+VALUE  Shiva-Disconnect-Reason Admin-Disconnect        5
+VALUE  Shiva-Disconnect-Reason Dialback                6
+VALUE  Shiva-Disconnect-Reason Virtual-Connection      7
+VALUE  Shiva-Disconnect-Reason Bandwidth-On-Demand     8
+VALUE  Shiva-Disconnect-Reason Failed-Authentication   9
+VALUE  Shiva-Disconnect-Reason Preempted               10
+VALUE  Shiva-Disconnect-Reason Blocked                 11
+VALUE  Shiva-Disconnect-Reason Tariff-Management       12
+VALUE  Shiva-Disconnect-Reason Backup                  13
+
+#      Shiva Function Values
+
+VALUE  Shiva-Function          Unknown                 0
+VALUE  Shiva-Function          Dialin                  1
+VALUE  Shiva-Function          Dialout                 2
+VALUE  Shiva-Function          Lan-To-Lan              3
+
diff --git a/share/dictionary.tunnel b/share/dictionary.tunnel
new file mode 100644 (file)
index 0000000..01692a3
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# dictionary.tunnel
+#
+#              Experimental tunneling attributes.
+#
+#
+# Version:     @(#)dictionary.tunnel  1.10  11-Nov-1998  miquels@cistron.nl
+#
+
+#
+#      Tunneling Attributes
+#
+ATTRIBUTE      Tunnel-Type                     64      integer
+ATTRIBUTE      Tunnel-Medium-Type              65      integer
+ATTRIBUTE      Acct-Tunnel-Client-Endpoint     66      string
+ATTRIBUTE      Tunnel-Server-Endpoint          67      string
+ATTRIBUTE      Acct-Tunnel-Connection-Id       68      string
+ATTRIBUTE      Tunnel-Password                 69      string
+ATTRIBUTE      Private-Group-Id                75      integer
+
+VALUE          Framed-Protocol         PPTP                    9
+
+#  Some of the new Tunnel values 
+VALUE          Tunnel-Security         None                    0
+VALUE          Tunnel-Security         Control-Only            1
+VALUE          Tunnel-Security         Data-Only               2
+VALUE          Tunnel-Security         Both                    3
+
+#      Tunnel Type
+
+VALUE          Tunnel-Type     PPTP    1
+VALUE          Tunnel-Type     L2F     2
+VALUE          Tunnel-Type     L2TP    3
+VALUE          Tunnel-Type     ATMP    4
+VALUE          Tunnel-Type     VTP     5
+VALUE          Tunnel-Type     AH      6
+VALUE          Tunnel-Type     IP      7
+VALUE          Tunnel-Type     MIN-IP  8
+VALUE          Tunnel-Type     ESP     9
+VALUE          Tunnel-Type     GRE     10
+VALUE          Tunnel-Type     DVS     11
+#
+
+#      Tunnel Medium Type
+
+VALUE          Tunnel-Medium-Type      IP              1
+VALUE          Tunnel-Medium-Type      X25             2
+VALUE          Tunnel-Medium-Type      ATM             3
+VALUE          Tunnel-Medium-Type      Frame-Relay     4
+
diff --git a/share/dictionary.usr b/share/dictionary.usr
new file mode 100644 (file)
index 0000000..348044e
--- /dev/null
@@ -0,0 +1,876 @@
+#
+# dictionary.usr       USR Robotics dictionary.
+#
+#              Taken from the dictionary included with the USR RADIUS server,
+#              and adjusted a bit.
+#
+# Version:     @(#)dictionary.usr  1.10  11-Nov-1998  miquels@cistron.nl
+#
+
+#
+#      USR specific attributes
+#
+# Prompt value should be 1 for echo, 0 for no echo, default 1.
+#ATTRIBUTE     Prompt                  64      integer
+ATTRIBUTE      Multi-Link-Flag         126     integer
+ATTRIBUTE      Char-Noecho             250     integer
+
+#
+#      USR specific Integer Translations
+#
+
+VALUE          Termination-Action      Manage-Resources        2
+
+VALUE          Service-Type            Authenticate-User       8
+VALUE          Service-Type            Dialback-NAS-User       9
+
+VALUE          Acct-Status-Type        Modem-Start             4
+VALUE          Acct-Status-Type        Modem-Stop              5
+VALUE          Acct-Status-Type        Cancel                  6
+
+VALUE          Multi-Link-Flag         True                    1
+VALUE          Multi-Link-Flag         False                   0
+
+#      USR specific Authentication Types
+
+VALUE          Acct-Authentic          None                    0
+VALUE          Acct-Authentic          Remote                  3
+VALUE          Acct-Authentic          RADIUS                  4
+VALUE          Acct-Authentic          MNET                    5
+VALUE          Acct-Authentic          KCHAP                   6
+VALUE          Acct-Authentic          TACACS                  7
+VALUE          Acct-Authentic          Realm                   8
+VALUE          Acct-Authentic          Local                   9
+VALUE          Acct-Authentic          File                    10
+VALUE          Acct-Authentic          Local-VPN               11
+
+#
+#      USR Extensions: USR Vendor-Specific stuff.
+#
+#      For now in NMC format (whatever that stands for), though the
+#      normal vendor-specific format would work just as well.
+#
+#
+
+ATTRIB_NMC     USR-Last-Number-Dialed-Out              0x0066  string
+ATTRIB_NMC     USR-Last-Number-Dialed-In-DNIS          0x00E8  string
+ATTRIB_NMC     USR-Last-Callers-Number-ANI             0x00E9  string
+ATTRIB_NMC     USR-Channel                             0xBF38  integer 
+ATTRIB_NMC     USR-Event-Id                            0xBFBE  integer
+ATTRIB_NMC     USR-Event-Date-Time                     0xBF2F  date
+ATTRIB_NMC     USR-Call-Start-Date-Time                0xBFF7  date
+ATTRIB_NMC     USR-Call-End-Date-Time                  0xBFF6  date
+ATTRIB_NMC     USR-Default-DTE-Data-Rate               0x005E  integer
+ATTRIB_NMC     USR-Initial-Rx-Link-Data-Rate           0xBF2D  integer
+ATTRIB_NMC     USR-Final-Rx-Link-Data-Rate             0xBF2C  integer
+ATTRIB_NMC     USR-Initial-Tx-Link-Data-Rate           0x006A  integer
+ATTRIB_NMC     USR-Final-Tx-Link-Data-Rate             0x006B  integer
+ATTRIB_NMC     USR-Chassis-Temperature                 0xBF31  integer
+ATTRIB_NMC     USR-Chassis-Temp-Threshold              0xBE84  integer
+ATTRIB_NMC     USR-Actual-Voltage                      0xBF32  integer
+ATTRIB_NMC     USR-Expected-Voltage                    0xBF33  integer
+ATTRIB_NMC     USR-Power-Supply-Number                 0xBF34  integer
+ATTRIB_NMC     USR-Card-Type                           0xBE85  integer
+ATTRIB_NMC     USR-Chassis-Slot                        0xBF39  integer
+ATTRIB_NMC     USR-Sync-Async-Mode                     0x0067  integer
+ATTRIB_NMC     USR-Originate-Answer-Mode               0x0068  integer
+ATTRIB_NMC     USR-Modulation-Type                     0x006C  integer
+ATTRIB_NMC     USR-Connect-Term-Reason                 0x009B  integer
+ATTRIB_NMC     USR-Failure-to-Connect-Reason           0x0069  integer
+ATTRIB_NMC     USR-Equalization-Type                   0x006F  integer
+ATTRIB_NMC     USR-Fallback-Enabled                    0x0070  integer
+ATTRIB_NMC     USR-Connect-Time-Limit                  0xBFE7  integer
+ATTRIB_NMC     USR-Number-of-Rings-Limit               0xBFE6  integer
+ATTRIB_NMC     USR-DTE-Data-Idle-Timout                0x0048  integer
+ATTRIB_NMC     USR-Characters-Sent                     0x0071  integer
+ATTRIB_NMC     USR-Characters-Received                 0x0072  integer
+ATTRIB_NMC     USR-Blocks-Sent                         0x0075  integer
+ATTRIB_NMC     USR-Blocks-Received                     0x0076  integer
+ATTRIB_NMC     USR-Blocks-Resent                       0x0077  integer
+ATTRIB_NMC     USR-Retrains-Requested                  0x0078  integer
+ATTRIB_NMC     USR-Retrains-Granted                    0x0079  integer
+ATTRIB_NMC     USR-Line-Reversals                      0x007A  integer
+ATTRIB_NMC     USR-Number-Of-Characters-Lost           0x007B  integer
+ATTRIB_NMC     USR-Number-of-Blers                     0x007D  integer
+ATTRIB_NMC     USR-Number-of-Link-Timeouts             0x007E  integer
+ATTRIB_NMC     USR-Number-of-Fallbacks                 0x007F  integer
+ATTRIB_NMC     USR-Number-of-Upshifts                  0x0080  integer
+ATTRIB_NMC     USR-Number-of-Link-NAKs                 0x0081  integer
+ATTRIB_NMC     USR-DTR-False-Timeout                   0x00BE  integer
+ATTRIB_NMC     USR-Fallback-Limit                      0x00BF  integer
+ATTRIB_NMC     USR-Block-Error-Count-Limit             0x00C0  integer
+ATTRIB_NMC     USR-DTR-True-Timeout                    0x00DA  integer
+ATTRIB_NMC     USR-Security-Login-Limit                0xBEDE  integer
+ATTRIB_NMC     USR-Security-Resp-Limit                 0xBEFA  integer
+ATTRIB_NMC     USR-DTE-Ring-No-Answer-Limit            0xBF17  integer
+ATTRIB_NMC     USR-Back-Channel-Data-Rate              0x007C  integer
+ATTRIB_NMC     USR-Simplified-MNP-Levels               0x0099  integer
+ATTRIB_NMC     USR-Simplified-V42bis-Usage             0x00C7  integer
+ATTRIB_NMC     USR-Mbi_Ct_PRI_Card_Slot                0x0184  integer
+ATTRIB_NMC     USR-Mbi_Ct_TDM_Time_Slot                0x0185  integer
+ATTRIB_NMC     USR-Mbi_Ct_PRI_Card_Span_Line           0x0186  integer
+ATTRIB_NMC     USR-Mbi_Ct_BChannel_Used                0x0187  integer
+ATTRIB_NMC     USR-Physical-State                      0xBE77  integer
+ATTRIB_NMC     USR-Packet-Bus-Session                  0xBF14  integer
+ATTRIB_NMC     USR-Server-Time                         0xF000  date
+
+# 0xBE5D-0xBE63 sent with Event-Id 79
+ATTRIB_NMC     USR-Channel-Connected-To                0xBE5D  integer
+ATTRIB_NMC     USR-Slot-Connected-To                   0xBE5E  integer 
+ATTRIB_NMC     USR-Device-Connected-To                 0xBE5F  integer
+ATTRIB_NMC     USR-NFAS-ID                             0xBE60  integer
+ATTRIB_NMC     USR-Q931-Call-Reference-Value           0xBE61  integer
+ATTRIB_NMC     USR-Call-Event-Code                     0xBE62  integer
+ATTRIB_NMC     USR-DS0                                 0xBE63  integer
+# DS0s sent with Event-Id 77,78
+ATTRIB_NMC     USR-DS0s                                0xBE64  string
+# Gateway-IP-Address sent with Event-Id 71,72
+ATTRIB_NMC     USR-Gateway-IP-Address                  0xBE66  ipaddr
+
+
+#
+# These are CCA Radius attributes
+#
+ATTRIB_NMC     USR-PW_USR_IFilter_IP                   0x9000  string
+ATTRIB_NMC     USR-PW_USR_IFilter_IPX                  0x9001  string
+ATTRIB_NMC     USR-PW_USR_OFilter_IP                   0x9003  string
+ATTRIB_NMC     USR-PW_USR_OFilter_IPX                  0x9004  string
+ATTRIB_NMC     USR-PW_USR_OFilter_SAP                  0x9005  string
+ATTRIB_NMC     USR-PW_VPN_ID                           0x9006  string
+ATTRIB_NMC     USR-PW_VPN_Name                         0x9007  string
+ATTRIB_NMC     USR-PW_VPN_Neighbor                     0x9008  string
+ATTRIB_NMC     USR-PW_Framed_Routing_V2                0x9009  string
+ATTRIB_NMC     USR-PW_VPN_Gateway                      0x900a  string
+ATTRIB_NMC     USR-PW_Tunnel_Authentication            0x900b  string
+ATTRIB_NMC     USR-PW_Index                            0x900c  string
+ATTRIB_NMC     USR-PW_Cutoff                           0x900d  string
+ATTRIB_NMC     USR-PW_Packet                           0x900e  string
+ATTRIB_NMC     USR-Primary_DNS_Server                  0x900f  ipaddr
+ATTRIB_NMC     USR-Secondary_DNS_Server                0x9010  ipaddr
+ATTRIB_NMC     USR-Primary_NBNS_Server                 0x9011  ipaddr
+ATTRIB_NMC     USR-Secondary_NBNS_Server               0x9012  ipaddr
+ATTRIB_NMC     USR-Syslog-Tap                          0x9013  integer
+ATTRIB_NMC     USR-Chassis-Call-Slot                   0x9019  integer
+ATTRIB_NMC     USR-Chassis-Call-Span                   0x901A  integer
+ATTRIB_NMC     USR-Chassis-Call-Channel                0x901B  integer
+ATTRIB_NMC     USR-Keypress-Timeout                    0x901C  integer
+ATTRIB_NMC     USR-Unauthenticated-Time                0x901D  integer
+ATTRIB_NMC     USR-Connect-Speed                       0x9023  integer
+ATTRIB_NMC     USR-Framed_IP_Address_Pool_Name         0x9024  string
+ATTRIB_NMC     USR-MP-EDO                              0x9025  string  
+
+#
+# Pilgrim attributes
+# 
+ATTRIB_NMC     USR-Bearer-Capabilities                 0x9800  integer
+ATTRIB_NMC     USR-Speed-Of-Connection                 0x9801  integer
+ATTRIB_NMC     USR-Max-Channels                        0x9802  integer
+ATTRIB_NMC     USR-Channel-Expansion                   0x9803  integer
+ATTRIB_NMC     USR-Channel-Decrement                   0x9804  integer
+ATTRIB_NMC     USR-Expansion-Algorithm                 0x9805  integer
+ATTRIB_NMC     USR-Compression-Algorithm               0x9806  integer
+ATTRIB_NMC     USR-Receive-Acc-Map                     0x9807  integer
+ATTRIB_NMC     USR-Transmit-Acc-Map                    0x9808  integer
+ATTRIB_NMC     USR-Compression-Reset-Mode              0x980a  integer
+ATTRIB_NMC     USR-Min-Compression-Size                0x980b  integer
+ATTRIB_NMC     USR-IP                                  0x980c  integer
+ATTRIB_NMC     USR-IPX                                 0x980d  integer
+ATTRIB_NMC     USR-Filter-Zones                        0x980e  integer
+ATTRIB_NMC     USR-Appletalk                           0x980f  integer
+ATTRIB_NMC     USR-Bridging                            0x9810  integer
+ATTRIB_NMC     USR-Spoofing                            0x9811  integer
+ATTRIB_NMC     USR-Host-Type                           0x9812  integer
+ATTRIB_NMC     USR-Send-Name                           0x9813  string
+ATTRIB_NMC     USR-Send-Password                       0x9814  string
+ATTRIB_NMC     USR-Start-Time                          0x9815  integer
+ATTRIB_NMC     USR-End-Time                            0x9816  integer
+ATTRIB_NMC     USR-Send-Script1                        0x9817  string
+ATTRIB_NMC     USR-Reply-Script1                       0x9818  string
+ATTRIB_NMC     USR-Send-Script2                        0x9819  string
+ATTRIB_NMC     USR-Reply-Script2                       0x981a  string
+ATTRIB_NMC     USR-Send-Script3                        0x981b  string
+ATTRIB_NMC     USR-Reply-Script3                       0x981c  string
+ATTRIB_NMC     USR-Send-Script4                        0x981d  string
+ATTRIB_NMC     USR-Reply-Script4                       0x981e  string
+ATTRIB_NMC     USR-Send-Script5                        0x981f  string
+ATTRIB_NMC     USR-Reply-Script5                       0x9820  string
+ATTRIB_NMC     USR-Send-Script6                        0x9821  string
+ATTRIB_NMC     USR-Reply-Script6                       0x9822  string
+ATTRIB_NMC     USR-Terminal-Type                       0x9823  string
+ATTRIB_NMC     USR-Appletalk-Network-Range             0x9824  integer
+ATTRIB_NMC     USR-Local-IP-Address                    0x9825  string
+ATTRIB_NMC     USR-Routing-Protocol                    0x9826  integer
+ATTRIB_NMC     USR-Modem-Group                         0x9827  integer
+ATTRIB_NMC     USR-Modem-Training-Time                 0x9842  integer
+ATTRIB_NMC     USR-Interface-Index                     0x9843  integer
+ATTRIB_NMC     USR-MP-MRRU                             0x982f  integer
+
+#      Virtual Private Network Extensions
+#
+ATTRIB_NMC     USR-VPN-ID                      36870       integer
+ATTRIB_NMC     USR-VPN-Name                    36871       string
+ATTRIB_NMC     USR-VPN-Neighbor                36872       ipaddr
+ATTRIB_NMC     USR-RIPV2                       36873       integer
+ATTRIB_NMC     USR-VPN-Gateway                 36874       string
+ATTRIB_NMC     USR-VPN-Auth-Vector             36875       string
+ATTRIB_NMC     USR-RQ_INDEX                    36876       integer
+#USR_ATTRIBUTE     User-Cutoff                 36877      integer
+ATTRIB_NMC     USR-PACKET                      36878       string
+ATTRIB_NMC     USR-IP-Filter-In                36864       string
+ATTRIB_NMC     USR-IPX-Filter-In               36865       string
+ATTRIB_NMC     USR-SAP-Filter-In               36866       string
+ATTRIB_NMC     USR-IP-Filter-Out               36867       string
+ATTRIB_NMC     USR-IPX-Filter-Out              36868       string
+ATTRIB_NMC     USR-SAP-Filter-Out              36869       string
+ATTRIB_NMC     USR-Syslog-Tap                  36883       integer
+ATTRIB_NMC     USR-MIC                         36884       string
+ATTRIB_NMC     USR-Log-Filter-Packets          36887       string
+ATTRIB_NMC     USR-Chassis-Call-Slot           36889       integer
+ATTRIB_NMC     USR-Chassis-Call-Span           36890       integer
+ATTRIB_NMC     USR-Chassis-Call-Channel        36891       integer
+ATTRIB_NMC     USR-Keypress-Timeout            36892       integer
+ATTRIB_NMC     USR-Unauthenticated-Time        36893       integer
+ATTRIB_NMC     USR-VPN-Encrypter               36894       integer
+ATTRIB_NMC     USR-Re-Chap-Timeout             36896       integer
+ATTRIB_NMC     USR-Tunnel-Switch-Endpoint      39016       string
+
+# End of VPN crap
+
+#
+#      Integer Translations
+#
+
+#VALUE         USR-Character-Echo      Echo-On                 0
+#VALUE         USR-Character-Echo      Echo-Off                1
+
+VALUE          USR-RIPV2               Off                     0
+VALUE          USR-RIPV2               On                      1
+
+VALUE          USR-Syslog-Tap          Off                     0
+VALUE          USR-Syslog-Tap          On-Raw                  1
+VALUE          USR-Syslog-Tap          On-Framed               2
+VALUE          USR-Syslog-Tap          Unknown        4294967295
+
+
+#      Event Indentifiers
+
+VALUE  USR-Event-Id    Module-Inserted                 6
+VALUE  USR-Event-Id    Module-Removed                  7
+VALUE  USR-Event-Id    PSU-Voltage-Alarm               8
+VALUE  USR-Event-Id    PSU-Failed                      9
+VALUE  USR-Event-Id    HUB-Temp-Out-of-Range           10
+VALUE  USR-Event-Id    Fan-Failed                      11
+VALUE  USR-Event-Id    Watchdog-Timeout                12
+VALUE  USR-Event-Id    Mgmt-Bus-Failure                13
+VALUE  USR-Event-Id    In-Connection-Est               14
+VALUE  USR-Event-Id    Out-Connection-Est              15
+VALUE  USR-Event-Id    In-Connection-Term              16
+VALUE  USR-Event-Id    Out-Connection-Term             17
+VALUE  USR-Event-Id    Connection-Failed               18
+VALUE  USR-Event-Id    Connection-Timeout              19
+VALUE  USR-Event-Id    DTE-Transmit-Idle               20
+VALUE  USR-Event-Id    DTR-True                        21
+VALUE  USR-Event-Id    DTR-False                       22
+VALUE  USR-Event-Id    Block-Error-at-Threshold        23
+VALUE  USR-Event-Id    Fallbacks-at-Threshold          24
+VALUE  USR-Event-Id    No-Dial-Tone-Detected           25
+VALUE  USR-Event-Id    No-Loop-Current-Detected        26
+VALUE  USR-Event-Id    Yellow-Alarm                    27
+VALUE  USR-Event-Id    Red-Alarm                       28
+VALUE  USR-Event-Id    Loss-Of-Signal                  29
+VALUE  USR-Event-Id    Rcv-Alrm-Ind-Signal             30
+VALUE  USR-Event-Id    Timing-Source-Switch            31
+VALUE  USR-Event-Id    Modem-Reset-by-DTE              32
+VALUE  USR-Event-Id    Modem-Ring-No-Answer            33
+VALUE  USR-Event-Id    DTE-Ring-No-Answer              34
+VALUE  USR-Event-Id    Pkt-Bus-Session-Active          35
+VALUE  USR-Event-Id    Pkt-Bus-Session-Congestion      36
+VALUE  USR-Event-Id    Pkt-Bus-Session-Lost            37
+VALUE  USR-Event-Id    Pkt-Bus-Session-Inactive        38
+VALUE  USR-Event-Id    User-Interface-Reset            39
+VALUE  USR-Event-Id    Gateway-Port-Out-of-Service     40
+VALUE  USR-Event-Id    Gateway-Port-Link-Active        41
+VALUE  USR-Event-Id    Dial-Out-Login-Failure          42
+VALUE  USR-Event-Id    Dial-In-Login-Failure           43
+VALUE  USR-Event-Id    Dial-Out-Restricted-Number      44
+VALUE  USR-Event-Id    Dial-Back-Restricted-Number     45
+VALUE  USR-Event-Id    User-Blacklisted                46
+VALUE  USR-Event-Id    Attempted-Login-Blacklisted     47
+VALUE  USR-Event-Id    Response-Attempt-Limit-Exceeded 48
+VALUE  USR-Event-Id    Login-Attempt-Limit-Exceeded    49
+VALUE  USR-Event-Id    Dial-Out-Call-Duration          50
+VALUE  USR-Event-Id    Dial-In-Call-Duration           51
+VALUE  USR-Event-Id    Pkt-Bus-Session-Err-Status      52
+VALUE  USR-Event-Id    NMC-AutoRespnse-Trap            53
+VALUE  USR-Event-Id    Acct-Server-Contact-Loss        54
+VALUE  USR-Event-Id    Yellow-Alarm-Clear              55
+VALUE  USR-Event-Id    Red-Alarm-Clear                 56
+VALUE  USR-Event-Id    Loss-Of-Signal-Clear            57
+VALUE  USR-Event-Id    Rcv-Alrm-Ind-Signal-Clear       58
+VALUE  USR-Event-Id    Incoming-Connection-Established 59
+VALUE  USR-Event-Id    Outgoing-Connection-Established 60
+VALUE  USR-Event-Id    Incoming-Connection-Terminated  61
+VALUE  USR-Event-Id    Outgoing-Connection-Terminated  62
+VALUE  USR-Event-Id    Connection-Attempt-Failure      63
+VALUE  USR-Event-Id    Continuous-CRC-Alarm            64
+VALUE  USR-Event-Id    Continuous-CRC-Alarm-Clear      65
+VALUE  USR-Event-Id    Physical-State-Change           66
+VALUE  USR-Event-Id    Gateway-Network-Failed          71
+VALUE  USR-Event-Id    Gateway-Network-Restored        72
+VALUE  USR-Event-Id    Packet-Bus-Clock-Lost           73
+VALUE  USR-Event-Id    Packet-Bus-Clock-Restored       74
+VALUE  USR-Event-Id    D-Channel-In-Service            75
+VALUE  USR-Event-Id    D-Channel-Out-of-Service        76
+VALUE  USR-Event-Id    DS0s-In-Service                 77
+VALUE  USR-Event-Id    DS0s-Out-of-Service             78
+VALUE  USR-Event-Id    T1/T1PRI/E1PRI-Call-Event       79
+VALUE  USR-Event-Id    Psu-Incompatible                80
+
+
+VALUE  USR-Card-Type   SlotEmpty                       1
+VALUE  USR-Card-Type   SlotUnknown                     2
+VALUE  USR-Card-Type   NetwMgtCard                     3
+VALUE  USR-Card-Type   DualT1NAC                       4
+VALUE  USR-Card-Type   DualModemNAC                    5
+VALUE  USR-Card-Type   QuadModemNAC                    6
+VALUE  USR-Card-Type   TrGatewayNAC                    7
+VALUE  USR-Card-Type   X25GatewayNAC                   8
+VALUE  USR-Card-Type   DualV34ModemNAC                 9
+VALUE  USR-Card-Type   QuadV32DigitalModemNAC          10
+VALUE  USR-Card-Type   QuadV32AnalogModemNAC           11
+VALUE  USR-Card-Type   QuadV32DigAnlModemNAC           12
+VALUE  USR-Card-Type   QuadV34DigModemNAC              13
+VALUE  USR-Card-Type   QuadV34AnlModemNAC              14
+VALUE  USR-Card-Type   QuadV34DigAnlModemNAC           15
+VALUE  USR-Card-Type   SingleT1NAC                     16
+VALUE  USR-Card-Type   EthernetGatewayNAC              17
+VALUE  USR-Card-Type   AccessServer                    18
+VALUE  USR-Card-Type   486TrGatewayNAC                 19
+VALUE  USR-Card-Type   486EthernetGatewayNAC           20
+VALUE  USR-Card-Type   DualRS232NAC                    22
+VALUE  USR-Card-Type   486X25GatewayNAC                23
+VALUE  USR-Card-Type   ApplicationServerNAC            25
+VALUE  USR-Card-Type   ISDNGatewayNAC                  26
+VALUE  USR-Card-Type   ISDNpriT1NAC                    27
+VALUE  USR-Card-Type   ClkedNetMgtCard                 28
+VALUE  USR-Card-Type   ModemPoolManagementNAC          29
+VALUE  USR-Card-Type   ModemPoolNetserverNAC           30
+VALUE  USR-Card-Type   ModemPoolV34ModemNAC            31
+VALUE  USR-Card-Type   ModemPoolISDNNAC                32
+VALUE  USR-Card-Type   NTServerNAC                     33
+VALUE  USR-Card-Type   QuadV34DigitalG2NAC             34
+VALUE  USR-Card-Type   QuadV34AnalogG2NAC              35
+VALUE  USR-Card-Type   QuadV34DigAnlgG2NAC             36
+VALUE  USR-Card-Type   NETServerFrameRelayNAC          37
+VALUE  USR-Card-Type   NETServerTokenRingNAC           38
+VALUE  USR-Card-Type   X2524ChannelNAC                 39
+VALUE  USR-Card-Type   WirelessGatewayNac              42
+
+VALUE  USR-Card-Type   EnhancedAccessServer              44
+VALUE  USR-Card-Type   EnhancedISDNGatewayNAC            45
+
+VALUE  USR-Card-Type   DualT1NIC                       1001
+VALUE  USR-Card-Type   DualAlogMdmNIC                  1002
+VALUE  USR-Card-Type   QuadDgtlMdmNIC                  1003
+VALUE  USR-Card-Type   QuadAlogDgtlMdmNIC              1004
+VALUE  USR-Card-Type   TokenRingNIC                    1005
+VALUE  USR-Card-Type   SingleT1NIC                     1006
+VALUE  USR-Card-Type   EthernetNIC                     1007
+VALUE  USR-Card-Type   ShortHaulDualT1NIC              1008
+VALUE  USR-Card-Type   DualAlogMgdIntlMdmNIC           1009
+VALUE  USR-Card-Type   X25NIC                          1010
+VALUE  USR-Card-Type   QuadAlogNonMgdMdmNIC            1011
+VALUE  USR-Card-Type   QuadAlogMgdIntlMdmNIC           1012
+VALUE  USR-Card-Type   QuadAlogNonMgdIntlMdmNIC        1013
+VALUE  USR-Card-Type   QuadLsdLiMgdMdmNIC              1014
+VALUE  USR-Card-Type   QuadLsdLiNonMgdMdmNIC           1015
+VALUE  USR-Card-Type   QuadLsdLiMgdIntlMdmNIC          1016
+VALUE  USR-Card-Type   QuadLsdLiNonMgdIntlMdmNIC       1017
+VALUE  USR-Card-Type   HSEthernetWithV35NIC            1018
+VALUE  USR-Card-Type   HSEthernetWithoutV35NIC         1019
+VALUE  USR-Card-Type   DualHighSpeedV35NIC             1020
+VALUE  USR-Card-Type   QuadV35RS232LowSpeedNIC         1021
+VALUE  USR-Card-Type   DualE1NIC                       1022
+VALUE  USR-Card-Type   ShortHaulDualE1NIC              1023
+VALUE  USR-Card-Type   BellcoreLongHaulDualT1NIC       1025
+VALUE  USR-Card-Type   BellcoreShrtHaulDualT1NIC       1026
+VALUE  USR-Card-Type   SCSIEdgeServerNIC               1027
+
+
+VALUE  USR-Default-DTE-Data-Rate             110-BPS         1
+VALUE  USR-Default-DTE-Data-Rate             300-BPS         2
+VALUE  USR-Default-DTE-Data-Rate             600-BPS         3
+VALUE  USR-Default-DTE-Data-Rate             1200-BPS        4
+VALUE  USR-Default-DTE-Data-Rate             2400-BPS        5
+VALUE  USR-Default-DTE-Data-Rate             4800-BPS        6
+VALUE  USR-Default-DTE-Data-Rate             7200-BPS        7
+VALUE  USR-Default-DTE-Data-Rate             9600-BPS        8
+VALUE  USR-Default-DTE-Data-Rate             12K-BPS         9
+VALUE  USR-Default-DTE-Data-Rate             14.4K-BPS       10
+VALUE  USR-Default-DTE-Data-Rate             16.8-BPS        11
+VALUE  USR-Default-DTE-Data-Rate             19.2K-BPS       12
+VALUE  USR-Default-DTE-Data-Rate             38.4K-BPS       13
+VALUE  USR-Default-DTE-Data-Rate             75-BPS          14
+VALUE  USR-Default-DTE-Data-Rate             450-BPS         15
+VALUE  USR-Default-DTE-Data-Rate             UNKNOWN-BPS     16
+VALUE  USR-Default-DTE-Data-Rate             57.6K-BPS       17
+VALUE  USR-Default-DTE-Data-Rate             21.6K-BPS       18
+VALUE  USR-Default-DTE-Data-Rate             24K-BPS         19
+VALUE  USR-Default-DTE-Data-Rate             26K-BPS         20
+VALUE  USR-Default-DTE-Data-Rate             28K-BPS         21
+VALUE  USR-Default-DTE-Data-Rate             115K-BPS        22
+
+
+VALUE  USR-Initial-Rx-Link-Data-Rate   110-BPS         1
+VALUE  USR-Initial-Rx-Link-Data-Rate   300-BPS         2
+VALUE  USR-Initial-Rx-Link-Data-Rate   600-BPS         3
+VALUE  USR-Initial-Rx-Link-Data-Rate   1200-BPS        4
+VALUE  USR-Initial-Rx-Link-Data-Rate   2400-XBPS       5
+VALUE  USR-Initial-Rx-Link-Data-Rate   4800-BPS        6
+VALUE  USR-Initial-Rx-Link-Data-Rate   7200-BPS        7
+VALUE  USR-Initial-Rx-Link-Data-Rate   9600-BPS        8
+VALUE  USR-Initial-Rx-Link-Data-Rate   12K-BPS         9
+VALUE  USR-Initial-Rx-Link-Data-Rate   14.4K-BPS       10
+VALUE  USR-Initial-Rx-Link-Data-Rate   16.8-BPS        11
+VALUE  USR-Initial-Rx-Link-Data-Rate   19.2K-BPS       12
+VALUE  USR-Initial-Rx-Link-Data-Rate   38.4K-BPS       13
+VALUE  USR-Initial-Rx-Link-Data-Rate   75-BPS          14
+VALUE  USR-Initial-Rx-Link-Data-Rate   450-BPS         15
+VALUE  USR-Initial-Rx-Link-Data-Rate   UNKNOWN-BPS     16
+VALUE  USR-Initial-Rx-Link-Data-Rate   57.6K-BPS       17
+VALUE  USR-Initial-Rx-Link-Data-Rate   21.6K-BPS       18
+VALUE  USR-Initial-Rx-Link-Data-Rate   24K-BPS         19
+VALUE  USR-Initial-Rx-Link-Data-Rate   26K-BPS         20
+VALUE  USR-Initial-Rx-Link-Data-Rate   28K-BPS         21
+VALUE  USR-Initial-Rx-Link-Data-Rate   115K-BPS        22
+VALUE  USR-Initial-Rx-Link-Data-Rate   31K-BPS         23
+VALUE  USR-Initial-Rx-Link-Data-Rate   33K-BPS         24
+VALUE  USR-Initial-Rx-Link-Data-Rate   32K-BPS         25
+VALUE  USR-Initial-Rx-Link-Data-Rate   36K-BPS         26
+VALUE  USR-Initial-Rx-Link-Data-Rate   40K-BPS         27
+VALUE  USR-Initial-Rx-Link-Data-Rate   44K-BPS         28
+VALUE  USR-Initial-Rx-Link-Data-Rate   48K-BPS         29
+VALUE  USR-Initial-Rx-Link-Data-Rate   49333-BPS       30
+VALUE  USR-Initial-Rx-Link-Data-Rate   50666-BPS       31
+VALUE  USR-Initial-Rx-Link-Data-Rate   52K-BPS         32
+VALUE  USR-Initial-Rx-Link-Data-Rate   53333-BPS       33
+VALUE  USR-Initial-Rx-Link-Data-Rate   54666-BPS       34
+VALUE  USR-Initial-Rx-Link-Data-Rate   56K-BPS         35
+VALUE  USR-Initial-Rx-Link-Data-Rate   57333-BPS       36
+VALUE  USR-Initial-Rx-Link-Data-Rate   58666-BPS       37
+VALUE  USR-Initial-Rx-Link-Data-Rate   60K-BPS         38
+VALUE  USR-Initial-Rx-Link-Data-Rate   61333-BPS       39
+VALUE  USR-Initial-Rx-Link-Data-Rate   64K-BPS         40
+
+
+VALUE  USR-Final-Rx-Link-Data-Rate             110-BPS         1
+VALUE  USR-Final-Rx-Link-Data-Rate             300-BPS         2
+VALUE  USR-Final-Rx-Link-Data-Rate             600-BPS         3
+VALUE  USR-Final-Rx-Link-Data-Rate             1200-BPS        4
+VALUE  USR-Final-Rx-Link-Data-Rate             2400-BPS        5
+VALUE  USR-Final-Rx-Link-Data-Rate             4800-BPS        6
+VALUE  USR-Final-Rx-Link-Data-Rate             7200-BPS        7
+VALUE  USR-Final-Rx-Link-Data-Rate             9600-BPS        8
+VALUE  USR-Final-Rx-Link-Data-Rate             12K-BPS         9
+VALUE  USR-Final-Rx-Link-Data-Rate             14.4K-BPS       10
+VALUE  USR-Final-Rx-Link-Data-Rate             16.8-BPS        11
+VALUE  USR-Final-Rx-Link-Data-Rate             19.2K-BPS       12
+VALUE  USR-Final-Rx-Link-Data-Rate             38.4K-BPS       13
+VALUE  USR-Final-Rx-Link-Data-Rate             75-BPS          14
+VALUE  USR-Final-Rx-Link-Data-Rate             450-BPS         15
+VALUE  USR-Final-Rx-Link-Data-Rate             UNKNOWN-BPS     16
+VALUE  USR-Final-Rx-Link-Data-Rate             57.6K-BPS       17
+VALUE  USR-Final-Rx-Link-Data-Rate             21.6K-BPS       18
+VALUE  USR-Final-Rx-Link-Data-Rate             24K-BPS         19
+VALUE  USR-Final-Rx-Link-Data-Rate             26K-BPS         20
+VALUE  USR-Final-Rx-Link-Data-Rate             28K-BPS         21
+VALUE  USR-Final-Rx-Link-Data-Rate             115K-BPS        22
+VALUE  USR-Final-Rx-Link-Data-Rate             31K-BPS         23
+VALUE  USR-Final-Rx-Link-Data-Rate             33K-BPS         24
+VALUE  USR-Final-Rx-Link-Data-Rate             32K-BPS         25
+VALUE  USR-Final-Rx-Link-Data-Rate             36K-BPS         26
+VALUE  USR-Final-Rx-Link-Data-Rate             40K-BPS         27
+VALUE  USR-Final-Rx-Link-Data-Rate             44K-BPS         28
+VALUE  USR-Final-Rx-Link-Data-Rate             48K-BPS         29
+VALUE  USR-Final-Rx-Link-Data-Rate             49333-BPS       30
+VALUE  USR-Final-Rx-Link-Data-Rate             50666-BPS       31
+VALUE  USR-Final-Rx-Link-Data-Rate             52K-BPS         32
+VALUE  USR-Final-Rx-Link-Data-Rate             53333-BPS       33
+VALUE  USR-Final-Rx-Link-Data-Rate             54666-BPS       34
+VALUE  USR-Final-Rx-Link-Data-Rate             56K-BPS         35
+VALUE  USR-Final-Rx-Link-Data-Rate             57333-BPS       36
+VALUE  USR-Final-Rx-Link-Data-Rate             58666-BPS       37
+VALUE  USR-Final-Rx-Link-Data-Rate             60K-BPS         38
+VALUE  USR-Final-Rx-Link-Data-Rate             61333-BPS       39
+VALUE  USR-Final-Rx-Link-Data-Rate             64K-BPS         40
+
+
+VALUE  USR-Initial-Tx-Link-Data-Rate   110-BPS         1
+VALUE  USR-Initial-Tx-Link-Data-Rate   300-BPS         2
+VALUE  USR-Initial-Tx-Link-Data-Rate   600-BPS         3
+VALUE  USR-Initial-Tx-Link-Data-Rate   1200-BPS        4
+VALUE  USR-Initial-Tx-Link-Data-Rate   2400-BPS        5
+VALUE  USR-Initial-Tx-Link-Data-Rate   4800-BPS        6
+VALUE  USR-Initial-Tx-Link-Data-Rate   7200-BPS        7
+VALUE  USR-Initial-Tx-Link-Data-Rate   9600-BPS        8
+VALUE  USR-Initial-Tx-Link-Data-Rate   12K-BPS         9
+VALUE  USR-Initial-Tx-Link-Data-Rate   14.4K-BPS       10
+VALUE  USR-Initial-Tx-Link-Data-Rate   16.8-BPS        11
+VALUE  USR-Initial-Tx-Link-Data-Rate   19.2K-BPS       12
+VALUE  USR-Initial-Tx-Link-Data-Rate   38.4K-BPS       13
+VALUE  USR-Initial-Tx-Link-Data-Rate   75-BPS          14
+VALUE  USR-Initial-Tx-Link-Data-Rate   450-BPS         15
+VALUE  USR-Initial-Tx-Link-Data-Rate   UNKNOWN-BPS     16
+VALUE  USR-Initial-Tx-Link-Data-Rate   57.6K-BPS       17
+VALUE  USR-Initial-Tx-Link-Data-Rate   21.6K-BPS       18
+VALUE  USR-Initial-Tx-Link-Data-Rate   24K-BPS         19
+VALUE  USR-Initial-Tx-Link-Data-Rate   26K-BPS         20
+VALUE  USR-Initial-Tx-Link-Data-Rate   28K-BPS         21
+VALUE  USR-Initial-Tx-Link-Data-Rate   115K-BPS        22
+VALUE  USR-Initial-Tx-Link-Data-Rate   31K-BPS         23      
+VALUE  USR-Initial-Tx-Link-Data-Rate   33K-BPS         24
+VALUE  USR-Initial-Tx-Link-Data-Rate   32K-BPS         25
+VALUE  USR-Initial-Tx-Link-Data-Rate   36K-BPS         26
+VALUE  USR-Initial-Tx-Link-Data-Rate   40K-BPS         27
+VALUE  USR-Initial-Tx-Link-Data-Rate   44K-BPS         28
+VALUE  USR-Initial-Tx-Link-Data-Rate   48K-BPS         29
+VALUE  USR-Initial-Tx-Link-Data-Rate   49333-BPS       30
+VALUE  USR-Initial-Tx-Link-Data-Rate   50666-BPS       31
+VALUE  USR-Initial-Tx-Link-Data-Rate   52K-BPS         32
+VALUE  USR-Initial-Tx-Link-Data-Rate   53333-BPS       33
+VALUE  USR-Initial-Tx-Link-Data-Rate   54666-BPS       34
+VALUE  USR-Initial-Tx-Link-Data-Rate   56K-BPS         35
+VALUE  USR-Initial-Tx-Link-Data-Rate   57333-BPS       36
+VALUE  USR-Initial-Tx-Link-Data-Rate   58666-BPS       37
+VALUE  USR-Initial-Tx-Link-Data-Rate   60K-BPS         38
+VALUE  USR-Initial-Tx-Link-Data-Rate   61333-BPS       39
+VALUE  USR-Initial-Tx-Link-Data-Rate   64K-BPS         40
+
+
+VALUE  USR-Final-Tx-Link-Data-Rate             110-BPS         1
+VALUE  USR-Final-Tx-Link-Data-Rate             300-BPS         2
+VALUE  USR-Final-Tx-Link-Data-Rate             600-BPS         3
+VALUE  USR-Final-Tx-Link-Data-Rate             1200-BPS        4
+VALUE  USR-Final-Tx-Link-Data-Rate             2400-BPS        5
+VALUE  USR-Final-Tx-Link-Data-Rate             4800-BPS        6
+VALUE  USR-Final-Tx-Link-Data-Rate             7200-BPS        7
+VALUE  USR-Final-Tx-Link-Data-Rate             9600-BPS        8
+VALUE  USR-Final-Tx-Link-Data-Rate             12K-BPS         9
+VALUE  USR-Final-Tx-Link-Data-Rate             14.4K-BPS       10
+VALUE  USR-Final-Tx-Link-Data-Rate             16.8-BPS        11
+VALUE  USR-Final-Tx-Link-Data-Rate             19.2K-BPS       12
+VALUE  USR-Final-Tx-Link-Data-Rate             38.4K-BPS       13
+VALUE  USR-Final-Tx-Link-Data-Rate             75-BPS          14
+VALUE  USR-Final-Tx-Link-Data-Rate             450-BPS         15
+VALUE  USR-Final-Tx-Link-Data-Rate             UNKNOWN-BPS     16
+VALUE  USR-Final-Tx-Link-Data-Rate             57.6K-BPS       17
+VALUE  USR-Final-Tx-Link-Data-Rate             21.6K-BPS       18
+VALUE  USR-Final-Tx-Link-Data-Rate             24K-BPS         19
+VALUE  USR-Final-Tx-Link-Data-Rate             26K-BPS         20
+VALUE  USR-Final-Tx-Link-Data-Rate             28K-BPS         21
+VALUE  USR-Final-Tx-Link-Data-Rate             115K-BPS        22
+VALUE  USR-Final-Tx-Link-Data-Rate             31K-BPS         23
+VALUE  USR-Final-Tx-Link-Data-Rate             33K-BPS         24
+VALUE  USR-Final-Tx-Link-Data-Rate             32K-BPS         25
+VALUE  USR-Final-Tx-Link-Data-Rate             36K-BPS         26
+VALUE  USR-Final-Tx-Link-Data-Rate             40K-BPS         27
+VALUE  USR-Final-Tx-Link-Data-Rate             44K-BPS         28
+VALUE  USR-Final-Tx-Link-Data-Rate             48K-BPS         29
+VALUE  USR-Final-Tx-Link-Data-Rate             49333-BPS       30
+VALUE  USR-Final-Tx-Link-Data-Rate             50666-BPS       31
+VALUE  USR-Final-Tx-Link-Data-Rate             52K-BPS         32
+VALUE  USR-Final-Tx-Link-Data-Rate             53333-BPS       33
+VALUE  USR-Final-Tx-Link-Data-Rate             54666-BPS       34
+VALUE  USR-Final-Tx-Link-Data-Rate             56K-BPS         35
+VALUE  USR-Final-Tx-Link-Data-Rate             57333-BPS       36
+VALUE  USR-Final-Tx-Link-Data-Rate             58666-BPS       37
+VALUE  USR-Final-Tx-Link-Data-Rate             60K-BPS         38
+VALUE  USR-Final-Tx-Link-Data-Rate             61333-BPS       39
+VALUE  USR-Final-Tx-Link-Data-Rate             64K-BPS         40
+
+# Value Connect Speed  /* Added by Krish */
+
+VALUE  USR-Connect-Speed  NONE     0 
+VALUE  USR-Connect-Speed  300_BPS          1 
+VALUE  USR-Connect-Speed  1200_BPS          2 
+VALUE  USR-Connect-Speed  2400_BPS          3 
+VALUE  USR-Connect-Speed  4800_BPS          4 
+VALUE  USR-Connect-Speed  7200_BPS          5 
+VALUE  USR-Connect-Speed  9600_BPS          6 
+VALUE  USR-Connect-Speed  12000_BPS      7 
+VALUE  USR-Connect-Speed  14400_BPS      8 
+VALUE  USR-Connect-Speed  16800_BPS      9
+VALUE  USR-Connect-Speed  19200_BPS     10 
+VALUE  USR-Connect-Speed  21600_BPS     11 
+VALUE  USR-Connect-Speed  28800_BPS     12 
+VALUE  USR-Connect-Speed  38400_BPS     13 
+VALUE  USR-Connect-Speed  57600_BPS     14 
+VALUE  USR-Connect-Speed  44000_BPS     27 
+VALUE  USR-Connect-Speed  45333_BPS     28 
+VALUE  USR-Connect-Speed  46666_BPS     29 
+VALUE  USR-Connect-Speed  48000_BPS     30 
+VALUE  USR-Connect-Speed  49333_BPS     31 
+VALUE  USR-Connect-Speed  50666_BPS     32 
+VALUE  USR-Connect-Speed  52000_BPS     33 
+VALUE  USR-Connect-Speed  53333_BPS     34 
+VALUE  USR-Connect-Speed  54666_BPS     35 
+VALUE  USR-Connect-Speed  56000_BPS     36 
+VALUE  USR-Connect-Speed  57333_BPS     37 
+VALUE  USR-Connect-Speed  64000_BPS     38 
+VALUE  USR-Connect-Speed  25333_BPS     39 
+VALUE  USR-Connect-Speed  26666_BPS      40
+VALUE  USR-Connect-Speed  28000_BPS      41 
+VALUE  USR-Connect-Speed  115200_BPS     15 
+VALUE  USR-Connect-Speed  288000_BPS      16
+VALUE  USR-Connect-Speed  75_1200_BPS    17 
+VALUE  USR-Connect-Speed  1200_75_BPS    18
+VALUE  USR-Connect-Speed  24000_BPS      19
+VALUE  USR-Connect-Speed  26400_BPS      20
+VALUE  USR-Connect-Speed  31200_BPS      21
+VALUE  USR-Connect-Speed  33600_BPS      22
+VALUE  USR-Connect-Speed  33333_BPS      23
+VALUE  USR-Connect-Speed  37333_BPS      24
+VALUE  USR-Connect-Speed  41333_BPS      25
+VALUE  USR-Connect-Speed  42666_BPS      26
+VALUE  USR-Connect-Speed  29333_BPS      42 
+VALUE  USR-Connect-Speed  30666_BPS      43
+VALUE  USR-Connect-Speed  32000_BPS      44 
+VALUE  USR-Connect-Speed  34666_BPS      45 
+VALUE  USR-Connect-Speed  36000_BPS      46 
+VALUE  USR-Connect-Speed  38666_BPS      47 
+VALUE  USR-Connect-Speed  40000_BPS      48 
+VALUE  USR-Connect-Speed  58666_BPS      49 
+VALUE  USR-Connect-Speed  60000_BPS      50 
+VALUE  USR-Connect-Speed  61333_BPS      51 
+VALUE  USR-Connect-Speed  62666_BPS      52 
+
+# End of Connect-Speed / * Added by Krish */
+
+#
+
+VALUE  USR-Sync-Async-Mode             Asynchronous                    1
+VALUE  USR-Sync-Async-Mode             Synchronous                     2
+
+VALUE  USR-Originate-Answer-Mode       Originate_in_Originate_Mode     1
+VALUE  USR-Originate-Answer-Mode       Originate_in_Answer_Mode        2
+VALUE  USR-Originate-Answer-Mode       Answer_in_Originate_Mode        3
+VALUE  USR-Originate-Answer-Mode       Answer_in_Answer_Mode           4
+
+VALUE  USR-Modulation-Type             usRoboticsHST                   1
+VALUE  USR-Modulation-Type             ccittV32                        2
+VALUE  USR-Modulation-Type             ccittV22bis                     3
+VALUE  USR-Modulation-Type             bell103                         4
+VALUE  USR-Modulation-Type             ccittV21                        5
+VALUE  USR-Modulation-Type             bell212                         6
+VALUE  USR-Modulation-Type             ccittV32bis                     7
+VALUE  USR-Modulation-Type             ccittV23                        8
+VALUE  USR-Modulation-Type             negotiationFailed               9
+VALUE  USR-Modulation-Type             bell208b                        10
+VALUE  USR-Modulation-Type             v21FaxClass1                    11
+VALUE  USR-Modulation-Type             v27FaxClass1                    12
+VALUE  USR-Modulation-Type             v29FaxClass1                    13
+VALUE  USR-Modulation-Type             v17FaxClass1                    14
+VALUE  USR-Modulation-Type             v21FaxClass2                    15
+VALUE  USR-Modulation-Type             v27FaxClass2                    16
+VALUE  USR-Modulation-Type             v29FaxClass2                    17
+VALUE  USR-Modulation-Type             v17FaxClass2                    18
+VALUE  USR-Modulation-Type             v32Terbo                        19
+VALUE  USR-Modulation-Type             v34                             20
+VALUE  USR-Modulation-Type             vFC                             21
+VALUE  USR-Modulation-Type             v34plus                         22
+
+VALUE  USR-Connect-Term-Reason dtrDrop                         1
+VALUE  USR-Connect-Term-Reason escapeSequence                  2
+VALUE  USR-Connect-Term-Reason athCommand                      3
+VALUE  USR-Connect-Term-Reason carrierLoss                     4
+VALUE  USR-Connect-Term-Reason inactivityTimout                5
+VALUE  USR-Connect-Term-Reason mnpIncompatible                 6
+VALUE  USR-Connect-Term-Reason undefined                       7
+VALUE  USR-Connect-Term-Reason remotePassword                  8
+VALUE  USR-Connect-Term-Reason linkPassword                    9
+VALUE  USR-Connect-Term-Reason retransmitLimit                 10
+VALUE  USR-Connect-Term-Reason linkDisconnectMsgReceived       11
+VALUE  USR-Connect-Term-Reason noLoopCurrent                   12
+VALUE  USR-Connect-Term-Reason invalidSpeed                    13
+VALUE  USR-Connect-Term-Reason unableToRetrain                 14
+VALUE  USR-Connect-Term-Reason managementCommand               15
+VALUE  USR-Connect-Term-Reason noDialTone                      16
+VALUE  USR-Connect-Term-Reason keyAbort                        17
+VALUE  USR-Connect-Term-Reason lineBusy                        18
+VALUE  USR-Connect-Term-Reason noAnswer                        19
+VALUE  USR-Connect-Term-Reason voice                           20
+VALUE  USR-Connect-Term-Reason noAnswerTone                    21
+VALUE  USR-Connect-Term-Reason noCarrier                       22
+VALUE  USR-Connect-Term-Reason undetermined                    23
+VALUE  USR-Connect-Term-Reason v42SabmeTimeout                 24
+VALUE  USR-Connect-Term-Reason v42BreakTimeout                 25
+VALUE  USR-Connect-Term-Reason v42DisconnectCmd                26
+VALUE  USR-Connect-Term-Reason v42IdExchangeFail               27
+VALUE  USR-Connect-Term-Reason v42BadSetup                     28
+VALUE  USR-Connect-Term-Reason v42InvalidCodeWord              29
+VALUE  USR-Connect-Term-Reason v42StringToLong                 30
+VALUE  USR-Connect-Term-Reason v42InvalidCommand               31
+VALUE  USR-Connect-Term-Reason none                            32      
+VALUE  USR-Connect-Term-Reason v32Cleardown                    33
+VALUE  USR-Connect-Term-Reason dialSecurity                    34
+VALUE  USR-Connect-Term-Reason remoteAccessDenied              35
+VALUE  USR-Connect-Term-Reason loopLoss                        36
+VALUE  USR-Connect-Term-Reason ds0Teardown                     37
+VALUE  USR-Connect-Term-Reason promptNotEnabled                38
+VALUE  USR-Connect-Term-Reason noPromptingInSync               39
+VALUE  USR-Connect-Term-Reason nonArqMode                      40
+VALUE  USR-Connect-Term-Reason modeIncompatible                41
+VALUE  USR-Connect-Term-Reason noPromptInNonARQ                42
+VALUE  USR-Connect-Term-Reason dialBackLink                    43
+VALUE  USR-Connect-Term-Reason linkAbort                       44
+VALUE  USR-Connect-Term-Reason autopassFailed                  45
+VALUE  USR-Connect-Term-Reason pbGenericError                  46
+VALUE  USR-Connect-Term-Reason pbLinkErrTxPreAck               47
+VALUE  USR-Connect-Term-Reason pbLinkErrTxTardyACK             48
+VALUE  USR-Connect-Term-Reason pbTransmitBusTimeout            49
+VALUE  USR-Connect-Term-Reason pbReceiveBusTimeout             50
+VALUE  USR-Connect-Term-Reason pbLinkErrTxTAL                  51
+VALUE  USR-Connect-Term-Reason pbLinkErrRxTAL                  52
+VALUE  USR-Connect-Term-Reason pbTransmitMasterTimeout         53
+VALUE  USR-Connect-Term-Reason pbClockMissing                  54
+VALUE  USR-Connect-Term-Reason pbReceivedLsWhileLinkUp         55
+VALUE  USR-Connect-Term-Reason pbOutOfSequenceFrame            56
+VALUE  USR-Connect-Term-Reason pbBadFrame                      57
+VALUE  USR-Connect-Term-Reason pbAckWaitTimeout                58
+VALUE  USR-Connect-Term-Reason pbReceivedAckSeqErr             59
+VALUE  USR-Connect-Term-Reason pbReceiveOvrflwRNRFail          60
+VALUE  USR-Connect-Term-Reason pbReceiveMsgBufOvrflw           61
+VALUE  USR-Connect-Term-Reason rcvdGatewayDiscCmd              62
+VALUE  USR-Connect-Term-Reason tokenPassingTimeout             63
+VALUE  USR-Connect-Term-Reason dspInterruptTimeout             64
+VALUE  USR-Connect-Term-Reason mnpProtocolViolation            65
+VALUE  USR-Connect-Term-Reason class2FaxHangupCmd              66
+VALUE  USR-Connect-Term-Reason hstSpeedSwitchTimeout           67
+
+VALUE  USR-Failure-to-Connect-Reason   dtrDrop                 1
+VALUE  USR-Failure-to-Connect-Reason   escapeSequence          2
+VALUE  USR-Failure-to-Connect-Reason   athCommand              3
+VALUE  USR-Failure-to-Connect-Reason   carrierLoss             4
+VALUE  USR-Failure-to-Connect-Reason   inactivityTimout        5
+VALUE  USR-Failure-to-Connect-Reason   mnpIncompatible         6
+VALUE  USR-Failure-to-Connect-Reason   undefined               7
+VALUE  USR-Failure-to-Connect-Reason   remotePassword          8
+VALUE  USR-Failure-to-Connect-Reason   linkPassword            9
+VALUE  USR-Failure-to-Connect-Reason   retransmitLimit         10
+VALUE  USR-Failure-to-Connect-Reason   linkDisconnectMsgRec    11
+VALUE  USR-Failure-to-Connect-Reason   noLoopCurrent           12
+VALUE  USR-Failure-to-Connect-Reason   invalidSpeed            13
+VALUE  USR-Failure-to-Connect-Reason   unableToRetrain         14
+VALUE  USR-Failure-to-Connect-Reason   managementCommand       15
+VALUE  USR-Failure-to-Connect-Reason   noDialTone              16
+VALUE  USR-Failure-to-Connect-Reason   keyAbort                17
+VALUE  USR-Failure-to-Connect-Reason   lineBusy                18
+VALUE  USR-Failure-to-Connect-Reason   noAnswer                19
+VALUE  USR-Failure-to-Connect-Reason   voice                   20
+VALUE  USR-Failure-to-Connect-Reason   noAnswerTone            21
+VALUE  USR-Failure-to-Connect-Reason   noCarrier               22
+VALUE  USR-Failure-to-Connect-Reason   undetermined            23
+VALUE  USR-Failure-to-Connect-Reason   v42SabmeTimeout         24
+VALUE  USR-Failure-to-Connect-Reason   v42BreakTimeout         25
+VALUE  USR-Failure-to-Connect-Reason   v42DisconnectCmd        26
+VALUE  USR-Failure-to-Connect-Reason   v42IdExchangeFail       27
+VALUE  USR-Failure-to-Connect-Reason   v42BadSetup             28
+VALUE  USR-Failure-to-Connect-Reason   v42InvalidCodeWord      29
+VALUE  USR-Failure-to-Connect-Reason   v42StringToLong         30
+VALUE  USR-Failure-to-Connect-Reason   v42InvalidCommand       31
+VALUE  USR-Failure-to-Connect-Reason   none                    32      
+VALUE  USR-Failure-to-Connect-Reason   v32Cleardown            33
+VALUE  USR-Failure-to-Connect-Reason   dialSecurity            34
+VALUE  USR-Failure-to-Connect-Reason   remoteAccessDenied      35
+VALUE  USR-Failure-to-Connect-Reason   loopLoss                36
+VALUE  USR-Failure-to-Connect-Reason   ds0Teardown             37
+VALUE  USR-Failure-to-Connect-Reason   promptNotEnabled        38
+VALUE  USR-Failure-to-Connect-Reason   noPromptingInSync       39
+VALUE  USR-Failure-to-Connect-Reason   nonArqMode              40
+VALUE  USR-Failure-to-Connect-Reason   modeIncompatible        41
+VALUE  USR-Failure-to-Connect-Reason   noPromptInNonARQ        42
+VALUE  USR-Failure-to-Connect-Reason   dialBackLink            43
+VALUE  USR-Failure-to-Connect-Reason   linkAbort               44
+VALUE  USR-Failure-to-Connect-Reason   autopassFailed          45
+VALUE  USR-Failure-to-Connect-Reason   pbGenericError          46
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrTxPreAck       47
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrTxTardyACK     48
+VALUE  USR-Failure-to-Connect-Reason   pbTransmitBusTimeout    49
+VALUE  USR-Failure-to-Connect-Reason   pbReceiveBusTimeout     50
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrTxTAL          51
+VALUE  USR-Failure-to-Connect-Reason   pbLinkErrRxTAL          52
+VALUE  USR-Failure-to-Connect-Reason   pbTransmitMasterTimeout 53
+VALUE  USR-Failure-to-Connect-Reason   pbClockMissing          54
+VALUE  USR-Failure-to-Connect-Reason   pbReceivedLsWhileLinkUp 55
+VALUE  USR-Failure-to-Connect-Reason   pbOutOfSequenceFrame    56
+VALUE  USR-Failure-to-Connect-Reason   pbBadFrame              57
+VALUE  USR-Failure-to-Connect-Reason   pbAckWaitTimeout        58
+VALUE  USR-Failure-to-Connect-Reason   pbReceivedAckSeqErr     59
+VALUE  USR-Failure-to-Connect-Reason   pbReceiveOvrflwRNRFail  60
+VALUE  USR-Failure-to-Connect-Reason   pbReceiveMsgBufOvrflw   61
+VALUE  USR-Failure-to-Connect-Reason   rcvdGatewayDiscCmd      62
+VALUE  USR-Failure-to-Connect-Reason   tokenPassingTimeout     63
+VALUE  USR-Failure-to-Connect-Reason   dspInterruptTimeout     64
+VALUE  USR-Failure-to-Connect-Reason   mnpProtocolViolation    65
+VALUE  USR-Failure-to-Connect-Reason   class2FaxHangupCmd      66
+VALUE  USR-Failure-to-Connect-Reason   hstSpeedSwitchTimeout   67
+
+VALUE  USR-Simplified-MNP-Levels               none                    1
+VALUE  USR-Simplified-MNP-Levels               mnpLevel3               2
+VALUE  USR-Simplified-MNP-Levels               mnpLevel4               3
+VALUE  USR-Simplified-MNP-Levels               ccittV42                4
+VALUE  USR-Simplified-MNP-Levels               usRoboticsHST           5
+VALUE  USR-Simplified-MNP-Levels               synchronousNone         6
+VALUE  USR-Simplified-MNP-Levels               mnpLevel2               7
+VALUE  USR-Simplified-MNP-Levels               mnp10                   8
+VALUE  USR-Simplified-MNP-Levels               v42Etc                  9
+
+VALUE  USR-Simplified-V42bis-Usage             none                    1
+VALUE  USR-Simplified-V42bis-Usage             ccittV42bis             2
+VALUE  USR-Simplified-V42bis-Usage             mnpLevel5               3
+
+VALUE  USR-Equalization-Type           Long            1
+VALUE  USR-Equalization-Type           Short           2
+
+
+VALUE  USR-Fallback-Enabled            Disabled        1
+VALUE  USR-Fallback-Enabled            Enabled         2
+
+
+VALUE  USR-Back-Channel-Data-Rate              450BPS          1
+VALUE  USR-Back-Channel-Data-Rate              300BPS          2
+VALUE  USR-Back-Channel-Data-Rate              None            3
+
+VALUE  USR-Device-Connected-To         None            1
+VALUE  USR-Device-Connected-To         isdnGateway     2
+VALUE  USR-Device-Connected-To         quadModem       3
+
+VALUE  USR-Call-Event-Code                     notSupported          1
+VALUE  USR-Call-Event-Code                     setup                 2
+VALUE  USR-Call-Event-Code                     usrSetup              3
+VALUE  USR-Call-Event-Code                     telcoDisconnect       4
+VALUE  USR-Call-Event-Code                     usrDisconnect         5
+VALUE  USR-Call-Event-Code                     noFreeModem           6
+VALUE  USR-Call-Event-Code                     modemsNotAllowed      7
+VALUE  USR-Call-Event-Code                     modemsRejectCall      8
+VALUE  USR-Call-Event-Code                     modemSetupTimeout     9
+VALUE  USR-Call-Event-Code                     noFreeIGW             10
+VALUE  USR-Call-Event-Code                     igwRejectCall         11
+VALUE  USR-Call-Event-Code                     igwSetupTimeout       12
+VALUE  USR-Call-Event-Code                     noFreeTdmts           13
+VALUE  USR-Call-Event-Code                     bcReject              14
+VALUE  USR-Call-Event-Code                     ieReject              15
+VALUE  USR-Call-Event-Code                     chidReject            16
+VALUE  USR-Call-Event-Code                     progReject            17
+VALUE  USR-Call-Event-Code                     callingPartyReject    18
+VALUE  USR-Call-Event-Code                     calledPartyReject     19
+VALUE  USR-Call-Event-Code                     blocked               20
+VALUE  USR-Call-Event-Code                     analogBlocked         21
+VALUE  USR-Call-Event-Code                     digitalBlocked        22
+VALUE  USR-Call-Event-Code                     outOfService          23
+VALUE  USR-Call-Event-Code                     busy                  24
+VALUE  USR-Call-Event-Code                     congestion            25
+VALUE  USR-Call-Event-Code                     protocolError         26 
+VALUE  USR-Call-Event-Code                     noFreeBchannel        27
+VALUE  USR-Call-Event-Code                     inOutCallCollision    28
+
diff --git a/share/dictionary.versanet b/share/dictionary.versanet
new file mode 100644 (file)
index 0000000..cd6a091
--- /dev/null
@@ -0,0 +1,50 @@
+#\r
+# dictionary.versanet Vendor specfic attributes for versanet\r
+#\r
+#\r
+#    VersaNet Communications, Inc.\r
+#     Http://www.versa-net.com\r
+#\r
+#\r
+#Versanet add Vendor specific terminal cause in our radius group.\r
+#You can follow this to set it in NAS box.\r
+#\r
+#          >> gr radius\r
+#          >> sh\r
+#          >> set 34 23\r
+#          >> co\r
+#\r
+#This will let our unit transfer every detail terminal cause \r
+#information to Redius server's accounting log file and  \r
+#save as "Vendor Specific=Terminate Cause". \r
+#\r
+# Version:   @(#)dictionary.versanet 1.00 22-Jul-1999 support@versanetcomm.com\r
+#\r
+\r
+VENDOR Versanet 2180\r
+\r
+ATTRIBUTE Versanet-Termination-Cause 1 integer Versanet\r
+\r
+VALUE Versanet-Termination-Cause Normal-Hangup-No-Error-Occurred 0\r
+VALUE Versanet-Termination-Cause Call-Waiting-Caused-Disconnect  3\r
+VALUE Versanet-Termination-Cause Physical-Carrier-Loss           4\r
+VALUE Versanet-Termination-Cause No-err-correction-at-other-end  5\r
+VALUE Versanet-Termination-Cause No-resp-to-feature-negotiation  6\r
+VALUE Versanet-Termination-Cause 1st-modem-async-only-2nd-sync   7\r
+VALUE Versanet-Termination-Cause No-framing-technique-in-common  8\r
+VALUE Versanet-Termination-Cause No-protocol-in-common           9\r
+VALUE Versanet-Termination-Cause Bad-resp-to-feature-negotiation 10\r
+VALUE Versanet-Termination-Cause No-sync-info-from-remote-modem  11\r
+VALUE Versanet-Termination-Cause Normal-Hangup-by-Remote-modem   12\r
+VALUE Versanet-Termination-Cause Retransmission-limit-reached    13\r
+VALUE Versanet-Termination-Cause Protocol-violation-occurred     14\r
+VALUE Versanet-Termination-Cause Lost-DTR                        15\r
+VALUE Versanet-Termination-Cause Received-GSTN-cleardown         16\r
+VALUE Versanet-Termination-Cause Inactivity-timeout              17\r
+VALUE Versanet-Termination-Cause Speed-not-supported             18\r
+VALUE Versanet-Termination-Cause Long-space-disconnect           19\r
+VALUE Versanet-Termination-Cause Key-abort-disconnect            20\r
+VALUE Versanet-Termination-Cause Clears-previous-disc-reason     21\r
+VALUE Versanet-Termination-Cause No-connection-established       22\r
+VALUE Versanet-Termination-Cause Disconnect-after-three-retrains 23\r
+\r
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644 (file)
index 0000000..6ba5acb
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Makefile     Makefile for the cistron-radius package.
+#
+# Version:     @(#)Makefile  1.00 01-Jul-1999  miquels@cistron.nl
+#
+
+@INCLUDE@ @IQUOTE@../Make.inc@IQUOTE@
+
+SUBDIRS                = lib modules main
+WHAT_TO_MAKE   = all
+
+all:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+clean:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+       @rm -f include/*~ *~
+
+install:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+common:
+       @for dir in $(SUBDIRS); do \
+               echo "Making $(WHAT_TO_MAKE) in $$dir..."; \
+               (cd $$dir ; $(MAKE) $(MFLAGS) $(WHAT_TO_MAKE)) || exit 1;\
+       done
+
diff --git a/src/include/autoconf.h.in b/src/include/autoconf.h.in
new file mode 100644 (file)
index 0000000..46bcba9
--- /dev/null
@@ -0,0 +1,96 @@
+/* src/include/autoconf.h.in.  Generated automatically from configure.in by autoheader.  */
+/*
+
+acconfig.h - template used by autoheader to create config.h.in
+config.h.in - used by autoconf to create config.h
+config.h - created by autoconf; contains defines generated by autoconf
+
+*/
+
+
+/* Define if you have the ANSI C header files.  */
+#undef STDC_HEADERS
+
+/* Do we have socklen_t? */
+#undef HAVE_SOCKLEN_T
+
+/* Do we have libdl support? */
+#undef HAVE_LIBDL
+
+/* Do we want to compile in DBM support? */
+#undef WITH_DBM
+
+/* Do we want to compile in NDBM support? */
+#undef WITH_NDBM
+
+/* Include Ascend hacks */
+#undef WITH_ASCEND_HACK
+
+/* Set Ascend Channels Per Line to N */
+#undef ASCEND_CHANNELS_PER_LINE
+
+/* Include NT Domain hack */
+#undef WITH_NTDOMAIN_HACK
+
+/* Include Specialix Jetstream hacks */
+#undef WITH_SPECIALIX_JETSTREAM_HACK
+
+/* Make dictionary case-independant */
+#undef WITH_DICT_NOCASE
+
+/* Make dictionary case-independant */
+#undef WITH_DICT_NOCASE
+
+/* Define if you have the getopt_long function.  */
+#undef HAVE_GETOPT_LONG
+
+/* Define if you have the lockf function.  */
+#undef HAVE_LOCKF
+
+/* Define if you have the setsid function.  */
+#undef HAVE_SETSID
+
+/* Define if you have the snprintf function.  */
+#undef HAVE_SNPRINTF
+
+/* Define if you have the strsignal function.  */
+#undef HAVE_STRSIGNAL
+
+/* Define if you have the vsnprintf function.  */
+#undef HAVE_VSNPRINTF
+
+/* Define if you have the <crypt.h> header file.  */
+#undef HAVE_CRYPT_H
+
+/* Define if you have the <dirent.h> header file.  */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <errno.h> header file.  */
+#undef HAVE_ERRNO_H
+
+/* Define if you have the <getopt.h> header file.  */
+#undef HAVE_GETOPT_H
+
+/* Define if you have the <malloc.h> header file.  */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <ndir.h> header file.  */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <resource.h> header file.  */
+#undef HAVE_RESOURCE_H
+
+/* Define if you have the <sys/dir.h> header file.  */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/ndir.h> header file.  */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/select.h> header file.  */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the nsl library (-lnsl).  */
+#undef HAVE_LIBNSL
+
+/* Define if you have the socket library (-lsocket).  */
+#undef HAVE_LIBSOCKET
diff --git a/src/include/conf.h b/src/include/conf.h
new file mode 100644 (file)
index 0000000..9489506
--- /dev/null
@@ -0,0 +1,53 @@
+/* Default Database File Names */
+
+#define RADIUS_DIR             RADDBDIR
+#define RADACCT_DIR            RADIR
+#define RADLOG_DIR             LOGDIR
+
+#define RADIUS_DICTIONARY      "dictionary"
+#define RADIUS_CLIENTS         "clients"
+#define RADIUS_NASLIST         "naslist"
+#define RADIUS_USERS           "users"
+#define RADIUS_HOLD            "holdusers"
+#define RADIUS_LOG             "radius.log"
+#define RADIUS_HINTS           "hints"
+#define RADIUS_HUNTGROUPS      "huntgroups"
+#define RADIUS_REALMS          "realms"
+#define RADIUS_MODULES         "modules"
+
+#define RADUTMP                        LOGDIR "/radutmp"
+#define RADWTMP                        LOGDIR "/radwtmp"
+
+#define RADIUS_PID             RUNDIR "/radiusd.pid"
+
+#define CHECKRAD               SBDIRDIR "/checkrad"
+
+/* Hack for funky ascend ports on MAX 4048 (and probably others)
+   The "NAS-Port-Id" value is "xyyzz" where "x" = 1 for digital, 2 for analog;
+   "yy" = line number (1 for first PRI/T1/E1, 2 for second, so on);
+   "zz" = channel number (on the PRI or Channelized T1/E1).
+    This should work with normal terminal servers, unless you have a TS with
+        more than 9999 ports ;^).
+    The "ASCEND_CHANNELS_PER_LINE" is the number of channels for each line into
+        the unit.  For my US/PRI that's 23.  A US/T1 would be 24, and a
+        European E1 would be 30 (I think ... never had one ;^).
+    This will NOT change the "NAS-Port-Id" reported in the detail log.  This
+        is simply to fix the dynamic IP assignments a la Cistron.
+    You can change the default of 23 with an argument to ./configure.
+    WARNING: This hack works for me, but I only have one PRI!!!  I've not
+        tested it on 2 or more (or with models other than the Max 4048)
+    Use at your own risk!
+  -- dgreer@austintx.com
+*/
+#if ASCEND_PORT_HACK
+#  ifndef ASCEND_CHANNELS_PER_LINE
+#    define ASCEND_CHANNELS_PER_LINE        23
+#  endif
+#endif
+
+/*
+ *     Hack for USR gear - uses a different Vendor-Specific attribute
+ *     packet layout, argh.
+ */
+#define ATTRIB_NMC
+
diff --git a/src/include/libradius.h b/src/include/libradius.h
new file mode 100644 (file)
index 0000000..be3a9ed
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * libradius.h Structures and prototypes
+ *             for the radius library.
+ *
+ * Version:    @(#)libradius.h  1.00  19-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+#include "radius.h"
+#include "token.h"
+
+#define AUTH_VECTOR_LEN                16
+#define MAX_STRING_LEN         254     /* RFC2138: string 0-253 octets */
+
+#ifdef _LIBRADIUS
+#  define AUTH_HDR_LEN         20
+#  define VENDORPEC_USR                429
+#  define VENDOR(x)            (x >> 16)
+#  define DEBUG                        if (librad_debug) printf
+#  define debug_pair(vp)       do { if (librad_debug) { \
+                                       putchar('\t'); \
+                                       vp_print(stdout, vp); \
+                                       putchar('\n'); \
+                                    } \
+                               } while(0)
+#endif
+
+typedef unsigned int UINT4;
+
+typedef struct dict_attr {
+       char                    name[32];
+       int                     attr;
+       int                     type;
+       int                     vendor;
+       struct dict_attr        *next;
+} DICT_ATTR;
+
+typedef struct dict_value {
+       char                    name[32];
+       char                    attrname[32];
+       int                     attr;
+       int                     value;
+       struct dict_value       *next;
+} DICT_VALUE;
+
+typedef struct dict_vendor {
+       char                    vendorname[32];
+       int                     vendorpec;
+       int                     vendorcode;
+       struct dict_vendor      *next;
+} DICT_VENDOR;
+
+typedef struct value_pair {
+       char                    name[32];
+       int                     attribute;
+       int                     type;
+       int                     length; /* of strvalue */
+       UINT4                   lvalue;
+       int                     operator;
+       int                     addport;
+       char                    strvalue[MAX_STRING_LEN];
+       struct value_pair       *next;
+} VALUE_PAIR;
+
+/*
+ *     vector:         Request authenticator from access-request packet
+ *                     Put in there by rad_decode, and must be put in the
+ *                     response RADIUS_PACKET as well before calling rad_send
+ *
+ *     verified:       Filled in by rad_decode for accounting-request packets
+ *
+ *     data,data_len:  Used between rad_recv and rad_decode.
+ */
+typedef struct radius_packet {
+       UINT4                   src_ipaddr;
+       UINT4                   dst_ipaddr;
+       u_short                 src_port;
+       u_short                 dst_port;
+       int                     id;
+       int                     code;
+       char                    vector[16];
+       time_t                  timestamp;
+       int                     verified;
+       char                    *data;
+       int                     data_len;
+       VALUE_PAIR              *vps;
+} RADIUS_PACKET;
+
+/*
+ *     Printing functions.
+ */
+void           vp_prints(char *out, int outlen, VALUE_PAIR *vp);
+void           vp_print(FILE *, VALUE_PAIR *);
+void           vp_printlist(FILE *, VALUE_PAIR *);
+#define                fprint_attr_val vp_print
+
+/*
+ *     Dictionary functions.
+ */
+int            dict_init(char *dir, char *fn);
+DICT_ATTR      *dict_attrbyvalue(int attr);
+DICT_ATTR      *dict_attrbyname(char *attr);
+DICT_VALUE     *dict_valbyattr(int attr, int val);
+DICT_VALUE     *dict_valbyname(char *val);
+int            dict_vendorcode(int);
+int            dict_vendorpec(int);
+
+#if 1 /* FIXME: compat */
+#define dict_attrget   dict_attrbyvalue
+#define dict_attrfind  dict_attrbyname
+#define dict_valfind   dict_valbyname
+/*#define dict_valget  dict_valbyattr almost but not quite*/
+#endif
+
+/* md5.c */
+
+void           librad_md5_calc(u_char *, u_char *, u_int);
+
+/* radius.c */
+int            rad_send(RADIUS_PACKET *, int fd, char *secret);
+RADIUS_PACKET  *rad_recv(int fd);
+int            rad_decode(RADIUS_PACKET *packet, char *secret);
+RADIUS_PACKET  *rad_alloc(int newvector);
+void           rad_free(RADIUS_PACKET *);
+int            rad_pwencode(char *encpw, int *len, char *secret, char *vector);
+int            rad_pwdecode(char *encpw, int len, char *secret, char *vector);
+int            calc_digest (RADIUS_PACKET *packet, char *secret);
+int            calc_acctdigest(RADIUS_PACKET *packet, char *secret,
+                       char *data, int len);
+
+/* valuepair.c */
+VALUE_PAIR     *paircreate(int attr, int type);
+void           pairfree(VALUE_PAIR *);
+VALUE_PAIR     *pairfind(VALUE_PAIR *, int);
+void           pairdelete(VALUE_PAIR **, int);
+void           pairadd(VALUE_PAIR **, VALUE_PAIR *);
+VALUE_PAIR     *paircopy(VALUE_PAIR *vp);
+VALUE_PAIR     *paircopy2(VALUE_PAIR *vp, int attr);
+void           pairmove(VALUE_PAIR **to, VALUE_PAIR **from);
+void           pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr);
+VALUE_PAIR     *pairread(char **ptr, int *eol);
+int            userparse(char *buffer, VALUE_PAIR **first_pair);
+
+/*
+ *     Error functions.
+ */
+#ifdef _LIBRADIUS
+void           librad_log(char *, ...);
+#endif
+void           librad_perror(char *, ...);
+extern char    *librad_errstr;
+extern int     librad_dodns;
+extern int     librad_debug;
+
+/*
+ *     Several handy miscellaneous functions.
+ */
+char *         ip_hostname (UINT4);
+UINT4          ip_getaddr (char *);
+char *         ip_ntoa(char *, UINT4);
+UINT4          ip_addr(char *);
+
diff --git a/src/include/md5.h b/src/include/md5.h
new file mode 100644 (file)
index 0000000..5b6560a
--- /dev/null
@@ -0,0 +1,76 @@
+/* GLOBAL.H - RSAREF types and constants
+ */
+
+/* PROTOTYPES should be set to one if and only if the compiler supports
+  function argument prototyping.
+  The following makes PROTOTYPES default to 0 if it has not already
+  been defined with C compiler flags.
+ */
+#ifndef PROTOTYPES
+#  if __STDC__
+#    define PROTOTYPES 1
+#  else
+#    define PROTOTYPES 0
+#  endif
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+
+/* UINT2 defines a two byte word */
+typedef unsigned short int UINT2;
+
+/* UINT4 defines a four byte word */
+#if defined(__alpha) && (defined(__osf__) || defined(__linux__))
+typedef unsigned int UINT4;
+#else
+typedef unsigned long int UINT4;
+#endif
+
+/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
+   If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
+  returns an empty list.
+ */
+#if PROTOTYPES
+#define PROTO_LIST(list) list
+#else
+#define PROTO_LIST(list) ()
+#endif
+
+/* MD5.H - header file for MD5C.C
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+/* MD5 context. */
+typedef struct {
+  UINT4 state[4];                                   /* state (ABCD) */
+  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];                         /* input buffer */
+} MD5_CTX;
+
+void MD5Init PROTO_LIST ((MD5_CTX *));
+void MD5Update PROTO_LIST
+  ((MD5_CTX *, unsigned char *, unsigned int));
+void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
+
diff --git a/src/include/modules.h b/src/include/modules.h
new file mode 100644 (file)
index 0000000..9237e30
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * module.h    Interface to the RADIUS module system.
+ *
+ * Version:    @(#)module.h  0.02  11-Aug-1999  miquels@cistron.nl
+ *
+ */
+
+typedef struct module_t {
+       char    *name;
+       int     type;                   /* reserved */
+       int     (*init)(int argc, char **argv);
+       int     (*authorize)(REQUEST *request, char *username,
+                       VALUE_PAIR **check_items, VALUE_PAIR **reply_items);
+       int     (*authenticate)(REQUEST *request, char *username,
+                       char *password);
+       int     (*accounting)(REQUEST *request);
+       int     (*detach)(void);
+} module_t;
+
+enum {
+  RLM_AUTH_FAIL = -2,          /* Failed (don't reply) */
+  RLM_AUTH_REJECT = -1,                /* authentication failed - reject */
+  RLM_AUTH_OK = 0,             /* OK */
+  RLM_AUTH_HANDLED = 1,                /* OK, handled (don't reply) */
+};
+enum {
+  RLM_AUTZ_REJECT = -3,                /* Reject user */
+  RLM_AUTZ_FAIL = -2,          /* Failed (don't reply) */
+  RLM_AUTZ_NOTFOUND = -1,      /* User not found - try next autorization */
+  RLM_AUTZ_OK = 0,             /* OK */
+  RLM_AUTZ_HANDLED = 1,                /* OK, handled (don't reply) */
+};
+enum {
+  RLM_ACCT_FAIL = -2,          /* Failed (don't reply) */
+  RLM_ACCT_FAIL_SOFT = -1,     /* Failed, but who cares. Continue */
+  RLM_ACCT_OK = 0,             /* OK */
+  RLM_ACCT_HANDLED = 1,                /* OK, handled (don't reply) */
+};
+#define RLM_ACCT_FAIL_HARD RLM_ACCT_FAIL
+
+int read_modules_file(char *filename);
+int module_authorize(REQUEST *request, char *username,
+       VALUE_PAIR **check_items, VALUE_PAIR **reply_items);
+int module_authenticate(int type, REQUEST *request,
+       char *username, char *password);
+int module_accounting(REQUEST *request);
+
diff --git a/src/include/radius.h b/src/include/radius.h
new file mode 100644 (file)
index 0000000..239f5d7
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * radius.h    Constants of the radius protocol.
+ *
+ * Version:    @(#)radius.h  1.10  24-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+
+#define PW_TYPE_STRING                 0
+#define PW_TYPE_INTEGER                        1
+#define PW_TYPE_IPADDR                 2
+#define PW_TYPE_DATE                   3
+
+#define        PW_AUTHENTICATION_REQUEST       1
+#define        PW_AUTHENTICATION_ACK           2
+#define        PW_AUTHENTICATION_REJECT        3
+#define        PW_ACCOUNTING_REQUEST           4
+#define        PW_ACCOUNTING_RESPONSE          5
+#define        PW_ACCOUNTING_STATUS            6
+#define PW_PASSWORD_REQUEST            7
+#define PW_PASSWORD_ACK                        8
+#define PW_PASSWORD_REJECT             9
+#define        PW_ACCOUNTING_MESSAGE           10
+#define PW_ACCESS_CHALLENGE            11
+
+#define        PW_USER_NAME                    1
+#define        PW_PASSWORD                     2
+#define        PW_CHAP_PASSWORD                3
+#define        PW_NAS_IP_ADDRESS               4
+#define        PW_NAS_PORT_ID                  5
+#define        PW_SERVICE_TYPE                 6
+#define        PW_FRAMED_PROTOCOL              7
+#define        PW_FRAMED_IP_ADDRESS            8
+#define        PW_FRAMED_IP_NETMASK            9
+#define        PW_FRAMED_ROUTING               10
+#define        PW_FILTER_ID                    11
+#define        PW_FRAMED_MTU                   12
+#define        PW_FRAMED_COMPRESSION           13
+#define        PW_LOGIN_IP_HOST                14
+#define        PW_LOGIN_SERVICE                15
+#define        PW_LOGIN_TCP_PORT               16
+#define PW_OLD_PASSWORD                        17
+#define PW_REPLY_MESSAGE               18
+#define PW_CALLBACK_NUMBER             19
+#define PW_CALLBACK_ID                 20
+#define PW_EXPIRATION                  21
+#define PW_FRAMED_ROUTE                        22
+#define PW_FRAMED_IPXNET               23
+#define PW_STATE                       24
+#define PW_CLASS                       25
+#define PW_VENDOR_SPECIFIC             26
+#define PW_SESSION_TIMEOUT             27
+#define PW_IDLE_TIMEOUT                        28
+#define PW_CALLED_STATION_ID           30
+#define PW_CALLING_STATION_ID          31
+#define PW_PROXY_STATE                 33
+
+#define PW_ACCT_STATUS_TYPE            40
+#define PW_ACCT_DELAY_TIME             41
+#define PW_ACCT_INPUT_OCTETS           42
+#define PW_ACCT_OUTPUT_OCTETS          43
+#define PW_ACCT_SESSION_ID             44
+#define PW_ACCT_AUTHENTIC              45
+#define PW_ACCT_SESSION_TIME           46
+#define PW_ACCT_INPUT_REQUESTS         47
+#define PW_ACCT_OUTPUT_REQUESTS                48
+
+#define PW_CHAP_CHALLENGE              60
+#define PW_NAS_PORT_TYPE               61
+#define PW_PORT_LIMIT                  62
+#define PW_CONNECT_INFO                        77
+
+#define PW_HUNTGROUP_NAME              221
+#define PW_AUTHTYPE                    1000
+#define PW_PREFIX                      1003
+#define PW_SUFFIX                      1004
+#define PW_GROUP                       1005
+#define PW_CRYPT_PASSWORD              1006
+#define PW_CONNECT_RATE                        1007
+#define PW_USER_CATEGORY               1029
+#define PW_GROUP_NAME                  1030
+#define PW_SIMULTANEOUS_USE            1034
+#define PW_STRIP_USERNAME              1035
+#define PW_FALL_THROUGH                        1036
+#define PW_ADD_PORT_TO_IP_ADDRESS      1037
+#define PW_EXEC_PROGRAM                        1038
+#define PW_EXEC_PROGRAM_WAIT           1039
+#define PW_HINT                                1040
+#define PAM_AUTH_ATTR                  1041
+#define PW_LOGIN_TIME                  1042
+#define PW_STRIPPED_USERNAME           1042
+
+/*
+ *     Integer Translations
+ */
+
+/*     User Types      */
+
+#define        PW_LOGIN_USER                   1
+#define        PW_FRAMED_USER                  2
+#define        PW_DIALBACK_LOGIN_USER          3
+#define        PW_DIALBACK_FRAMED_USER         4
+
+/*     Framed Protocols        */
+
+#define        PW_PPP                          1
+#define        PW_SLIP                         2
+
+/*     Framed Routing Values   */
+
+#define        PW_NONE                         0
+#define        PW_BROADCAST                    1
+#define        PW_LISTEN                       2
+#define        PW_BROADCAST_LISTEN             3
+
+/*     Framed Compression Types        */
+
+#define        PW_VAN_JACOBSEN_TCP_IP          1
+
+/*     Login Services  */
+
+#define        PW_TELNET                       0
+#define        PW_RLOGIN                       1
+#define        PW_TCP_CLEAR                    2
+#define        PW_PORTMASTER                   3
+
+/*     Authentication Level    */
+
+#define PW_AUTHTYPE_LOCAL              0
+#define PW_AUTHTYPE_SYSTEM             1
+#define PW_AUTHTYPE_SECURID            2
+#define PW_AUTHTYPE_CRYPT              3
+#define PW_AUTHTYPE_REJECT             4
+#define PW_AUTHTYPE_PAM                        253
+#define PW_AUTHTYPE_ACCEPT             254
+
+/*     Port Types              */
+
+#define PW_NAS_PORT_ASYNC              0
+#define PW_NAS_PORT_SYNC               1
+#define PW_NAS_PORT_ISDN               2
+#define PW_NAS_PORT_ISDN_V120          3
+#define PW_NAS_PORT_ISDN_V110          4
+
+/*     Status Types    */
+
+#define PW_STATUS_START                        1
+#define PW_STATUS_STOP                 2
+#define PW_STATUS_ALIVE                        3
+#define PW_STATUS_ACCOUNTING_ON                7
+#define PW_STATUS_ACCOUNTING_OFF       8
+
diff --git a/src/include/radiusd.h b/src/include/radiusd.h
new file mode 100644 (file)
index 0000000..e5a8f8b
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * radiusd.h   Structures, prototypes and global variables
+ *             for the Cistron Radius server.
+ *
+ * Version:    @(#)radiusd.h  2.00  19-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+#include "libradius.h"
+#include "conf.h"
+
+#define CHAP_VALUE_LENGTH               16
+
+#define PW_AUTH_UDP_PORT                1645
+#define PW_ACCT_UDP_PORT                1646
+
+typedef struct auth_req {
+       RADIUS_PACKET           *packet;
+       RADIUS_PACKET           *proxy;
+       char                    username[MAX_STRING_LEN];
+       char                    secret[32];
+       int                     child_pid;
+       time_t                  timestamp;
+       int                     finished;
+       struct auth_req         *next;
+} REQUEST;
+
+typedef struct client {
+       UINT4                   ipaddr;
+       char                    longname[256];
+       u_char                  secret[32];
+       char                    shortname[32];
+       struct client           *next;
+} CLIENT;
+
+typedef struct nas {
+       UINT4                   ipaddr;
+       char                    longname[256];
+       char                    shortname[32];
+       char                    nastype[32];
+       struct nas              *next;
+} NAS;
+
+typedef struct realm {
+       char                    realm[64];
+       char                    server[64];
+       UINT4                   ipaddr;
+       int                     auth_port;
+       int                     acct_port;
+       int                     striprealm;
+       struct realm            *next;
+} REALM;
+
+typedef struct pair_list {
+       char                    *name;
+       VALUE_PAIR              *check;
+       VALUE_PAIR              *reply;
+       int                     lineno;
+       struct pair_list        *next;
+} PAIR_LIST;
+
+#define DEBUG  if(debug_flag)log_debug
+#define DEBUG2  if (debug_flag > 1)log_debug
+
+#define SECONDS_PER_DAY                86400
+#define MAX_REQUEST_TIME       30
+#define CLEANUP_DELAY          5
+#define MAX_REQUESTS           255
+
+#define L_DBG                  1
+#define L_AUTH                 2
+#define L_INFO                 3
+#define L_ERR                  4
+#define L_PROXY                        5
+#define L_CONS                 128
+
+#ifndef FALSE
+#  define FALSE 0
+#endif
+#ifndef TRUE
+#  define TRUE 1
+#endif
+
+/* for paircompare_register */
+typedef int (*COMPARE)(VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR **);
+
+/*
+ *     Global variables.
+ */
+extern char            *progname;
+extern int             debug_flag;
+extern char            *radacct_dir;
+extern char            *radius_dir;
+extern char            *radius_libdir;
+extern UINT4           expiration_seconds;
+extern int             radius_pid;
+extern int             use_dbm;
+extern int             log_stripped_names;
+extern int             cache_passwd;
+extern UINT4           myip;
+extern int             log_auth_detail;
+extern int             log_auth;
+extern int             log_auth_pass;
+extern int             auth_port;
+extern int             acct_port;
+
+/*
+ *     Function prototypes.
+ */
+
+/* acct.c */
+int            rad_accounting(REQUEST *, int);
+
+/* radutmp.c */
+int            radutmp_add(REQUEST *);
+int            radutmp_zap(UINT4 nas, int port, char *user, time_t t);
+int            radutmp_checksimul(char *name, VALUE_PAIR *, int maxsimul);
+
+/* radiusd.c */
+void           debug_pair(FILE *, VALUE_PAIR *);
+int            log_err (char *);
+void           sig_cleanup(int);
+
+/* util.c */
+struct passwd  *rad_getpwnam(char *);
+#if defined (sun) && defined(__svr4__)
+void           (*sun_signal(int signo, void (*func)(int)))(int);
+#define signal sun_signal
+#endif
+void           request_free(REQUEST *request);
+RADIUS_PACKET *        build_reply(int code, REQUEST *request,
+                       VALUE_PAIR *vps, char *user_msg);
+
+/* files.c */
+CLIENT         *client_find(UINT4 ipno);
+char           *client_name(UINT4 ipno);
+int            read_clients_file(char *);
+REALM          *realm_find(char *);
+PAIR_LIST      *pairlist_read(char *file, int complain);
+void           pairlist_free(PAIR_LIST **);
+int            read_config_files(void);
+
+/* nas.c */
+int            read_naslist_file(char *);
+NAS            *nas_find(UINT4 ipno);
+char           *nas_name(UINT4 ipno);
+char           *nas_name2(RADIUS_PACKET *r);
+NAS            *nas_findbyname(char *nasname);
+
+/* version.c */
+void           version();
+
+/* log.c */
+int            log(int, char *, ...);
+int            log_debug(char *, ...);
+
+/* pam.c */
+#ifdef WITH_PAM
+int            pam_pass(char *name, char *passwd, const char *pamauth);
+#define PAM_DEFAULT_TYPE    "radius"
+#endif
+
+/* proxy.c */
+int proxy_send(REQUEST *request, int activefd);
+int proxy_receive(REQUEST *request, int activefd);
+
+/* auth.c */
+char           *auth_name(REQUEST *request, int do_cli);
+int            rad_mangle(REQUEST *request);
+int            rad_authenticate (REQUEST *, int);
+
+/* exec.c */
+char           *radius_xlate(char *, VALUE_PAIR *req, VALUE_PAIR *reply);
+int            radius_exec_program(char *, VALUE_PAIR *, VALUE_PAIR **,
+                       int, char **user_msg);
+
+/* timestr.c */
+int            timestr_match(char *, time_t);
+
+/* valuepair.c */
+int            paircompare_register(int attr, int otherattr, COMPARE func);
+void           paircompare_unregister(int attr, COMPARE func);
+int            paircmp(VALUE_PAIR *request, VALUE_PAIR *check,
+                       VALUE_PAIR **reply);
+void           pair_builtincompare_init(void);
+
diff --git a/src/include/radutmp.h b/src/include/radutmp.h
new file mode 100644 (file)
index 0000000..d837f5a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * radutmp.h   Definitions for the Radius UTMP file.
+ *
+ * Version:    @(#)radutmp  2.01  11-Feb-1998  miquels@cistron.nl
+ */
+
+#ifndef _RADUTMP_H
+#define _RADUTMP_H
+
+/*
+ *      Types of connection.
+ */
+#ifndef P_UNKNOWN
+#  define P_UNKNOWN       0
+#  define P_LOCAL         'L'
+#  define P_RLOGIN        'R'
+#  define P_SLIP          'S'
+#  define P_CSLIP         'C'
+#  define P_PPP           'P'
+#  define P_AUTOPPP       'A'
+#  define P_TELNET        'E'
+#  define P_TCPCLEAR      'T'
+#  define P_TCPLOGIN      'U'
+#  define P_CONSOLE       '!'
+#  define P_SHELL         'X'
+#endif
+
+#define P_IDLE         0
+#define P_LOGIN                1
+
+#define RUT_NAMESIZE 32
+
+struct radutmp {
+  char login[32];              /* Loginname */
+                               /* FIXME: extend to 48 or 64 bytes */
+  int  nas_port;               /* Port on the terminal server (32 bits). */
+  char session_id[8];          /* Radius session ID (first 8 bytes at least)*/
+                               /* FIXME: extend to 16 or 32 bytes */
+  unsigned int nas_address;    /* IP of portmaster. */
+  unsigned int framed_address; /* SLIP/PPP address or login-host. */
+  int proto;                   /* Protocol. */
+  time_t time;                 /* Time entry was last updated. */
+  time_t delay;                        /* Delay time of request */
+  int type;                    /* Type of entry (login/logout) */
+  char porttype;               /* Porttype (I=ISDN A=Async T=Async-ISDN */
+  char res1,res2,res3;         /* Fills up to one int */
+  char caller_id[16];          /* Calling-Station-ID */
+  char reserved[12];           /* 3 ints reserved */
+};
+
+#endif /* _RADUTMP_H */
diff --git a/src/include/sysutmp.h b/src/include/sysutmp.h
new file mode 100644 (file)
index 0000000..3b9210a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * sysutmp.h   Compatibility stuff for the different UTMP systems.
+ *
+ * Version:    @(#)sysutmp.h  1.0  01-Jul-1999
+ */
+
+#ifndef SYSUTMP_H_INCLUDED
+#define SYSUTMP_H_INCLUDED
+
+/* UTMP stuff. Uses utmpx on svr4 */
+#ifdef __svr4__
+#  include <utmpx.h>
+#  include <sys/fcntl.h>
+#  define utmp utmpx
+#  define UT_NAMESIZE  32
+#  define UT_LINESIZE  32
+#  define UT_HOSTSIZE  257
+#else
+#  include <utmp.h>
+#endif
+#ifdef __osf__
+#  define UT_NAMESIZE  32
+#  define UT_LINESIZE  32
+#  define UT_HOSTSIZE  64
+#endif
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(bsdi)
+#  ifndef UTMP_FILE
+#    define UTMP_FILE "/var/run/utmp"
+#  endif
+#  define ut_user ut_name
+#endif
+
+#endif /* SYSUTMP_H_INCLUDED */
diff --git a/src/include/token.h b/src/include/token.h
new file mode 100644 (file)
index 0000000..7d7305e
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * token.h     Special tokens.
+ *
+ * Version:    @(#)token.h  1.00  19-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+#define T_EOL          1
+#define T_LCBRACE      2
+#define T_RCBRACE      3
+#define T_LBRACE       4
+#define T_RBRACE       5
+#define T_COMMA                6
+
+#define T_EQSTART      7
+#define T_OP_ADD       7
+#define T_OP_SUB       8
+#define T_OP_SET       9
+#define T_OP_EQ                10
+#define T_OP_NE                11
+#define T_OP_GE                12
+#define T_OP_GT                13
+#define T_OP_LE                14
+#define T_OP_LT                15
+#define T_EQEND                15
+
+int    getword (char **ptr, char *buf, int buflen);
+int    gettoken(char **ptr, char *buf, int buflen);
+
diff --git a/src/lib/Makefile.in b/src/lib/Makefile.in
new file mode 100644 (file)
index 0000000..74b4bec
--- /dev/null
@@ -0,0 +1,45 @@
+
+@INCLUDE@ @IQUOTE@../../Make.inc@IQUOTE@
+
+OBJS           = dict.o md5.o print.o radius.o valuepair.o token.o misc.o log.o
+
+INCLUDES       = ../include/radius.h ../include/libradius.h
+BUILDDBM       = @BUILDDBM@
+
+CFLAGS         += -D_LIBRADIUS -I../include
+
+all:   libradius.a
+
+libradius.a: $(OBJS)
+       $(AR) rv libradius.a $(OBJS)
+       $(RANLIB) libradius.a
+
+print.o: print.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c print.c
+
+dict.o: dict.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c dict.c
+
+radius.o: radius.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c radius.c
+
+valuepair.o: valuepair.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c valuepair.c
+
+token.o: token.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c token.c
+
+misc.o: misc.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c misc.c
+
+log.o: log.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c log.c
+
+md5.o: md5.c md5.h
+       $(CC) $(CFLAGS) -c md5.c
+
+clean:
+       rm -f *.o libradius.a
+
+install:
+
diff --git a/src/lib/dict.c b/src/lib/dict.c
new file mode 100644 (file)
index 0000000..32308ab
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+ * dict.c      Routines to read the dictionary file.
+ *
+ * Version:    @(#)dict.c  2.30  25-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+#include       <autoconf.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <sys/types.h>
+#include       <pwd.h>
+#include       <ctype.h>
+#include       <string.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "libradius.h"
+
+static DICT_ATTR       *dictionary_attributes;
+static DICT_VALUE      *dictionary_values;
+static DICT_VENDOR     *dictionary_vendors;
+
+static int             vendorno = 1;
+static char *dtypes[] = {
+       "string",
+       "integer",
+       "ipaddr",
+       "date",
+       NULL,
+};
+
+#ifdef WITH_DICT_NOCASE
+#define DICT_STRCMP strcasecmp
+#else
+#define DICT_STRCMP strcmp
+#endif
+
+/*
+ *     Free the dictionary_attributes and dictionary_values lists.
+ */
+static void dict_free(void)
+{
+       DICT_ATTR       *dattr, *anext;
+       DICT_VALUE      *dval, *vnext;
+       DICT_VENDOR     *dvend, *enext;
+
+       for (dattr = dictionary_attributes; dattr; dattr = anext) {
+               anext = dattr->next;
+               free(dattr);
+       }
+       for (dval = dictionary_values; dval; dval = vnext) {
+               vnext = dval->next;
+               free(dval);
+       }
+       for (dvend = dictionary_vendors; dvend; dvend = enext) {
+               enext = dvend->next;
+               free(dvend);
+       }
+       dictionary_attributes = NULL;
+       dictionary_values = NULL;
+       dictionary_vendors = NULL;
+       vendorno = 1;
+}
+
+/*
+ *     Add vendor to the list.
+ */
+static int addvendor(char *name, int value)
+{
+       DICT_VENDOR *vval;
+
+       if ((vval =(DICT_VENDOR *)malloc(sizeof(DICT_VENDOR))) == NULL) {
+               librad_log("dict_init: out of memory");
+               return -1;
+       }
+       strcpy(vval->vendorname, name);
+       vval->vendorpec  = value;
+       vval->vendorcode = vendorno++;
+
+       /* Insert at front. */
+       vval->next = dictionary_vendors;
+       dictionary_vendors = vval;
+
+       return 0;
+}
+
+/*
+ *     Initialize the dictionary.
+ */
+static int my_dict_init(char *dir, char *fn)
+{
+       FILE    *fp;
+       DICT_ATTR       *attr;
+       DICT_VALUE      *dval;
+       DICT_VENDOR     *v;
+       char    dirtmp[256];
+       char    buf[256];
+       char    namestr[64];
+       char    valstr[64];
+       char    attrstr[64];
+       char    typestr[64];
+       char    vendorstr[64];
+       char    *p;
+       char    *keyword;
+       char    *data;
+       int     line = 0;
+       int     value;
+       int     type;
+       int     vendor;
+       int     is_attrib;
+#ifdef ATTRIB_NMC
+       int     vendor_usr_seen = 0;
+       int     is_nmc;
+#endif
+
+       /*
+        *      First see if fn is relative to dir. If so, create
+        *      new filename. If not, remember the absolute dir.
+        */
+       if ((p = strrchr(fn, '/')) != NULL) {
+               strcpy(dirtmp, fn);
+               dirtmp[p - fn] = 0;
+               dir = dirtmp;
+       } else if (dir && dir[0] && strcmp(dir, ".") != 0) {
+               sprintf(dirtmp, "%s/%s", dir, fn);
+               fn = dirtmp;
+       }
+
+       if ((fp = fopen(fn, "r")) == NULL) {
+               librad_log("dict_init: Couldn't open dictionary: %s", fn);
+               return -1;
+       }
+
+       while (fgets(buf, sizeof(buf), fp) != NULL) {
+
+               line++;
+               if (buf[0] == '#' || buf[0] == 0 || buf[0] == '\n')
+                       continue;
+
+               keyword = strtok(buf, " \t\n");
+               data    = strtok(NULL, "\n");
+               if (data == NULL || data[0] == 0) {
+                       librad_log("dict_init: %s[%d]: invalid entry",
+                               fn, line);
+                       return -1;
+               }
+
+               /*
+                *      See if we need to import another dictionary.
+                */
+               if (strcasecmp(keyword, "$INCLUDE") == 0) {
+                       if (my_dict_init(dir, data) < 0)
+                               return -1;
+                       continue;
+               }
+
+               /*
+                *      Perhaps this is an attribute.
+                */
+               is_attrib = 0;
+               if (strcmp(keyword, "ATTRIBUTE") == 0)
+                       is_attrib = 1;
+#ifdef ATTRIB_NMC
+               is_nmc = 0;
+               if (strcmp(keyword, "ATTRIB_NMC") == 0)
+                       is_attrib = is_nmc = 1;
+#endif
+               if (is_attrib) {
+
+                       vendor = 0;
+                       vendorstr[0] = 0;
+                       if(sscanf(data, "%s%s%s%s", namestr,
+                                       valstr, typestr, vendorstr) < 3) {
+                               librad_log(
+                                       "dict_init: %s[%d]: invalid attribute",
+                                       fn, line);
+                               return -1;
+                       }
+
+#ifdef ATTRIB_NMC
+                       /*
+                        *      Convert ATTRIB_NMC into our format.
+                        *      We might need to add USR to the list of
+                        *      vendors first.
+                        */
+                       if (is_nmc && vendorstr[0] == 0) {
+                               if (!vendor_usr_seen) {
+                                       if (addvendor("USR", VENDORPEC_USR) < 0)
+                                               return -1;
+                                       vendor_usr_seen = 1;
+                               }
+                               strcpy(vendorstr, "USR");
+                       }
+#endif
+                       /*
+                        *      Validate all entries
+                        */
+                       if (strlen(namestr) > 31) {
+                               librad_log(
+                               "dict_init: %s[%d]: invalid name length",
+                                       fn, line);
+                               return -1;
+                       }
+
+                       if (!isdigit(*valstr)) {
+                               librad_log("dict_init: %s[%d]: invalid value",
+                                       fn, line);
+                               return -1;
+                       }
+                       if (valstr[0] != '0')
+                               value = atoi(valstr);
+                       else
+                               sscanf(valstr, "%i", &value);
+
+                       /*
+                        *      find the type.
+                        */
+                       for (type = 0; dtypes[type]; type++) {
+                               if (strcmp(typestr, dtypes[type]) == 0)
+                                       break;
+                       }
+                       if (dtypes[type] == NULL) {
+                               librad_log("dict_init: %s[%d]: invalid type",
+                                       fn, line);
+                               return -1;
+                       }
+
+                       /*
+                        *      Find the vendor, if any.
+                        */
+                       for (v = dictionary_vendors; v; v = v->next) {
+                               if (strcmp(vendorstr, v->vendorname) == 0)
+                                       vendor = v->vendorcode;
+                       }
+                       if (vendorstr[0] && !vendor) {
+                               librad_log(
+                                       "dict_init: %s[%d]: unknown vendor %s",
+                                       fn, line, vendorstr);
+                               return -1;
+                       }
+
+                       /*
+                        *      Create a new attribute for the list
+                        */
+                       if ((attr = (DICT_ATTR *)malloc(sizeof(DICT_ATTR))) ==
+                                       NULL) {
+                               librad_log("dict_init: out of memory");
+                               return -1;
+                       }
+                       strcpy(attr->name, namestr);
+                       attr->attr = value;
+                       attr->type = type;
+                       if (vendor)
+                               attr->attr |= (vendor << 16);
+
+                       /*
+                        *      Add to the front of the list, so that
+                        *      values at the end of the file override
+                        *      those in the begin.
+                        */
+                       attr->next = dictionary_attributes;
+                       dictionary_attributes = attr;
+
+               }
+
+               /*
+                *      Process VALUE lines.
+                */
+               if (strcmp(keyword, "VALUE") == 0) {
+
+                       if (sscanf(data, "%s%s%s", attrstr,
+                                               namestr, valstr) != 3) {
+                               librad_log("dict_init: %s[%d]: invalid value",
+                                       fn, line);
+                               return -1;
+                       }
+                       /*
+                        *      For Compatibility, skip "Server-Config"
+                        */
+                       if (strcmp(attrstr, "Server-Config") == 0)
+                               continue;
+
+                       /*
+                        *      Validate all entries
+                        */
+                       if (strlen(attrstr) > 31) {
+                               librad_log(
+                               "dict_init: %s[%d]: invalid attribute length",
+                                       fn, line);
+                               return -1;
+                       }
+
+                       if (strlen(namestr) > 31) {
+                               librad_log(
+                               "dict_init: %s[%d]: invalid name length",
+                                       fn, line);
+                               return -1;
+                       }
+
+                       if (!isdigit(*valstr)) {
+                               librad_log("dict_init: %s[%d]: invalid value",
+                                       fn, line);
+                               return -1;
+                       }
+                       if (valstr[0] != '0')
+                               value = atoi(valstr);
+                       else
+                               sscanf(valstr, "%i", &value);
+
+                       if ((dval = (DICT_VALUE *)malloc(sizeof(DICT_VALUE))) ==
+                                       NULL) {
+                               librad_log("dict_init: out of memory");
+                               return -1;
+                       }
+
+                       strcpy(dval->name, namestr);
+                       strcpy(dval->attrname, attrstr);
+                       dval->attr = 0;
+                       dval->value = value;
+
+                       /* Insert at front. */
+                       dval->next = dictionary_values;
+                       dictionary_values = dval;
+               }
+
+               /*
+                *      Process VENDOR lines.
+                */
+               if (strcmp(keyword, "VENDOR") == 0) {
+
+                       if (sscanf(data, "%s%s", attrstr, valstr) != 2) {
+                               librad_log(
+                               "dict_init: %s[%d] invalid vendor entry",
+                                       fn, line);
+                               return -1;
+                       }
+
+                       /*
+                        *       Validate all entries
+                        */
+                       if (strlen(attrstr) > 31) {
+                               librad_log(
+                               "dict_init: %s[%d]: invalid attribute length",
+                                       fn, line);
+                               return -1;
+                       }
+
+                       if (!isdigit(*valstr)) {
+                               librad_log("dict_init: %s[%d]: invalid value",
+                                       fn, line);
+                               return -1;
+                       }
+                       value = atoi(valstr);
+
+                       /* Create a new VENDOR entry for the list */
+                       if (addvendor(attrstr, value) < 0)
+                               return -1;
+#ifdef ATTRIB_NMC
+                       if (value == VENDORPEC_USR)
+                               vendor_usr_seen = 1;
+#endif
+               }
+       }
+       fclose(fp);
+       return 0;
+}
+
+/*
+ *     Initialize the directory, then fix the attr member of
+ *     all attributes.
+ */
+int dict_init(char *dir, char *fn)
+{
+       DICT_ATTR       *attr;
+       DICT_VALUE      *dval;
+
+       dict_free();
+
+       if (my_dict_init(dir, fn) < 0)
+               return -1;
+
+       for (dval = dictionary_values; dval; dval = dval->next) {
+               if (dval->attr != 0)
+                       continue;
+               if ((attr = dict_attrbyname(dval->attrname)) == NULL) {
+               librad_log("dict_init: VALUE %s for unknown ATTRIBUTE %s",
+                       dval->name, dval->attrname);
+                       return -1;
+               }
+               dval->attr = attr->attr;
+       }
+
+       return 0;
+}
+
+/*
+ *     Get an attribute by its numerical value.
+ */
+DICT_ATTR * dict_attrbyvalue(int val)
+{
+       DICT_ATTR       *a;
+
+       for (a = dictionary_attributes; a; a = a->next) {
+               if (a->attr == val)
+                       return a;
+       }
+
+       return NULL;
+}
+
+/*
+ *     Get an attribute by its name.
+ */
+DICT_ATTR * dict_attrbyname(char *name)
+{
+       DICT_ATTR       *a;
+
+       for (a = dictionary_attributes; a; a = a->next) {
+               if (DICT_STRCMP(a->name, name) == 0)
+                       return a;
+       }
+
+       return NULL;
+}
+
+/*
+ *     Associate a value with an attribute and return it.
+ */
+DICT_VALUE * dict_valbyattr(int attr, int val)
+{
+       DICT_VALUE      *v;
+
+       for (v = dictionary_values; v; v = v->next) {
+               if (v->attr == attr && v->value == val)
+                       return v;
+       }
+
+       return NULL;
+}
+
+/*
+ *     Get a value by its name.
+ */
+DICT_VALUE * dict_valbyname(char *name)
+{
+       DICT_VALUE      *v;
+
+       for (v = dictionary_values; v; v = v->next) {
+               if (DICT_STRCMP(v->name, name) == 0)
+                       return v;
+       }
+
+       return NULL;
+}
+
+/*
+ *     Get the PEC (Private Enterprise Code) of the vendor
+ *     based on its internal number.
+ */
+int dict_vendorpec(int code)
+{
+       DICT_VENDOR     *v;
+
+       for (v = dictionary_vendors; v; v = v->next)
+               if (v->vendorcode == code)
+                       break;
+
+       return v ? v->vendorpec : 0;
+}
+
+/*
+ *     Get the internal code of the vendor based on its PEC.
+ */
+int dict_vendorcode(int pec)
+{
+       DICT_VENDOR     *v;
+
+       for (v = dictionary_vendors; v; v = v->next)
+               if (v->vendorpec == pec)
+                       break;
+       return v ? v->vendorcode : 0;
+}
+
diff --git a/src/lib/log.c b/src/lib/log.c
new file mode 100644 (file)
index 0000000..768567a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * log.c       Functions in the library call radlib_log() which
+ *             sets a global error string "char *librad_errstr".
+ *
+ * Version:    @(#)log.c  1.00  25-Oct-1998  miquels@cistron.nl
+ *
+ */
+
+#include "autoconf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+char librad_errstr[1024];
+
+void librad_log(char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+#ifdef HAVE_VSNPRINTF
+       vsnprintf(librad_errstr, sizeof(librad_errstr), fmt, ap);
+#else
+       vsprintf(librad_errstr, fmt, ap);
+#endif
+       va_end(ap);
+}
+
+void librad_perror(char *fmt, ...)
+{
+       va_list *ap;
+
+       va_start(ap, fmt);
+       vfprintf(stderr, fmt, ap);
+       if (strchr(fmt, ':') == NULL)
+               fprintf(stderr, ": ");
+       fprintf(stderr, "%s\n", librad_errstr);
+}
+
diff --git a/src/lib/md5.c b/src/lib/md5.c
new file mode 100644 (file)
index 0000000..053b0d6
--- /dev/null
@@ -0,0 +1,345 @@
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+ */
+
+#include "md5.h"
+
+/* Constants for MD5Transform routine.
+ */
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
+static void Encode PROTO_LIST
+  ((unsigned char *, UINT4 *, unsigned int));
+static void Decode PROTO_LIST
+  ((UINT4 *, unsigned char *, unsigned int));
+static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
+static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+
+void librad_md5_calc(output, input, inlen)
+unsigned char *output;
+unsigned char *input;                                /* input block */
+unsigned int inlen;                     /* length of input block */
+{
+       MD5_CTX context;
+
+       MD5Init(&context);
+       MD5Update(&context, input, inlen);
+       MD5Final(output, &context);
+}
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+void MD5Init (context)
+MD5_CTX *context;                                        /* context */
+{
+  context->count[0] = context->count[1] = 0;
+  /* Load magic initialization constants.
+*/
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+  operation, processing another message block, and updating the
+  context.
+ */
+void MD5Update (context, input, inputLen)
+MD5_CTX *context;                                        /* context */
+unsigned char *input;                                /* input block */
+unsigned int inputLen;                     /* length of input block */
+{
+  unsigned int i, index, partLen;
+
+  /* Compute number of bytes mod 64 */
+  index = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+  /* Update number of bits */
+  if ((context->count[0] += ((UINT4)inputLen << 3))
+   < ((UINT4)inputLen << 3))
+ context->count[1]++;
+  context->count[1] += ((UINT4)inputLen >> 29);
+
+  partLen = 64 - index;
+
+  /* Transform as many times as possible.
+*/
+  if (inputLen >= partLen) {
+ MD5_memcpy
+   ((POINTER)&context->buffer[index], (POINTER)input, partLen);
+ MD5Transform (context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+   MD5Transform (context->state, &input[i]);
+
+ index = 0;
+  }
+  else
+ i = 0;
+
+  /* Buffer remaining input */
+  MD5_memcpy
+ ((POINTER)&context->buffer[index], (POINTER)&input[i],
+  inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+  the message digest and zeroizing the context.
+ */
+void MD5Final (digest, context)
+unsigned char digest[16];                         /* message digest */
+MD5_CTX *context;                                       /* context */
+{
+  unsigned char bits[8];
+  unsigned int index, padLen;
+
+  /* Save number of bits */
+  Encode (bits, context->count, 8);
+
+  /* Pad out to 56 mod 64.
+*/
+  index = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (index < 56) ? (56 - index) : (120 - index);
+  MD5Update (context, PADDING, padLen);
+
+  /* Append length (before padding) */
+  MD5Update (context, bits, 8);
+
+  /* Store state in digest */
+  Encode (digest, context->state, 16);
+
+  /* Zeroize sensitive information.
+*/
+  MD5_memset ((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (state, block)
+UINT4 state[4];
+unsigned char block[64];
+{
+  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+  Decode (x, block, 64);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information.
+*/
+  MD5_memset ((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+  a multiple of 4.
+ */
+static void Encode (output, input, len)
+unsigned char *output;
+UINT4 *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+  a multiple of 4.
+ */
+static void Decode (output, input, len)
+UINT4 *output;
+unsigned char *input;
+unsigned int len;
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+   (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+/* Note: Replace "for loop" with standard memcpy if possible.
+ */
+
+static void MD5_memcpy (output, input, len)
+POINTER output;
+POINTER input;
+unsigned int len;
+{
+  unsigned int i;
+
+  for (i = 0; i < len; i++)
+ output[i] = input[i];
+}
+
+/* Note: Replace "for loop" with standard memset if possible.
+ */
+static void MD5_memset (output, value, len)
+POINTER output;
+int value;
+unsigned int len;
+{
+  unsigned int i;
+
+  for (i = 0; i < len; i++)
+ ((char *)output)[i] = (char)value;
+}
diff --git a/src/lib/misc.c b/src/lib/misc.c
new file mode 100644 (file)
index 0000000..176dda7
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * misc.c      Various miscellaneous functions.
+ *
+ * Version:     @(#)misc.c  1.00  19-Jul-1999  miquels@cistron.nl
+ */
+
+char misc_sccsid[] =
+"@(#)misc.c    1.00 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+#include       <arpa/inet.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <netdb.h>
+#include       <pwd.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <signal.h>
+
+#include       "libradius.h"
+
+int            librad_dodns = 1;
+int            librad_debug = 0;
+
+/*
+ *     Return a printable host name (or IP address in dot notation)
+ *     for the supplied IP address.
+ */
+char * ip_hostname(UINT4 ipaddr)
+{
+       struct          hostent *hp;
+       static char     hstname[128];
+
+       hp = gethostbyaddr((char *)&ipaddr, sizeof (struct in_addr), AF_INET);
+       if (hp == 0) {
+               ip_ntoa(hstname, ipaddr);
+               return(hstname);
+       }
+       return (char *)hp->h_name;
+}
+
+
+/*
+ *     Return an IP address in from a host
+ *     name or address in dot notation.
+ */
+UINT4 ip_getaddr(char *host)
+{
+       struct hostent  *hp;
+       UINT4           a, ip_addr();
+
+       if ((a = ip_addr(host)) != 0)
+               return a;
+
+       if ((hp = gethostbyname(host)) == NULL)
+               return (UINT4)0;
+
+       return (*(UINT4 *)hp->h_addr);
+}
+
+
+/*
+ *     Return an IP address in standard dot notation
+ */
+char *ip_ntoa(char *buffer, UINT4 ipaddr)
+{
+       struct in_addr  in;
+       char            *r;
+
+       in.s_addr = ipaddr;
+       r = inet_ntoa(in);
+
+       if (buffer)
+               strcpy(buffer, inet_ntoa(in));
+       return buffer ? buffer : r;
+}
+
+
+/*
+ *     Return an IP address from
+ *     one supplied in standard dot notation.
+ */
+UINT4 ip_addr(char *ip_str)
+{
+       struct in_addr  in;
+
+       if (inet_aton(ip_str, &in) == 0)
+               return 0;
+       return in.s_addr;
+}
+
diff --git a/src/lib/print.c b/src/lib/print.c
new file mode 100644 (file)
index 0000000..f29bc61
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * print.c     Routines to print stuff.
+ *
+ * Version:    @(#)print.c  1.00  26-Oct-1998  miquels@cistron.nl
+ *
+ */
+
+#include       "autoconf.h"
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <sys/types.h>
+#include       <time.h>
+#include       <pwd.h>
+#include       <ctype.h>
+#include       <string.h>
+
+#include       "libradius.h"
+
+/*
+ *     Convert a string to something printable.
+ *     The output string has to be _at least_ 4x the size
+ *     of the input string!
+ */
+static void librad_safeprint(char *in, int inlen, char *out, int outlen)
+{
+       unsigned char   *str = (unsigned char *)in;
+       int             done = 0;
+       int             sp = 0;
+
+       if (inlen < 0) inlen = strlen(str);
+
+       while (inlen-- > 0 && (done + 3) < outlen) {
+               /*
+                *      Hack: never print trailing zero.
+                *      Some clients send strings with an off-by-one
+                *      length (confused with strings in C).
+                */
+               if (inlen == 0 && *str == 0)
+                       break;
+
+               sp = 0;
+
+               switch (*str) {
+                       case '\\':
+                               sp = '\\';
+                               break;
+                       case '\r':
+                               sp = 'r';
+                               break;
+                       case '\n':
+                               sp = 'n';
+                               break;
+                       case '\t':
+                               sp = 't';
+                               break;
+                       default:
+                               if (*str < 32 || (*str >= 128 && *str <= 160)){
+                                       sprintf(out, "\\%03o", *str);
+                                       done += 4;
+                                       out  += 4;
+                               } else {
+                                       *out++ = *str;
+                                       done++;
+                               }
+               }
+               if (sp) {
+                       *out++ = '\\';
+                       *out++ = sp;
+                       done += 2;
+               }
+               str++;
+       }
+       *out = 0;
+}
+
+
+/*
+ *     Print one attribute and value into a string.
+ */
+void vp_prints(char *out, int outlen, VALUE_PAIR *vp)
+{
+       DICT_VALUE      *v;
+       char            buf[1024];
+       char            *a;
+       time_t          t;
+       int             len;
+
+       out[0] = 0;
+       if (strlen(vp->name) + 3 > outlen)
+               return;
+
+       sprintf(out, "%s = ", vp->name);
+       len = strlen(out);
+       outlen -= len;
+       out += len;
+
+       switch (vp->type) {
+               case PW_TYPE_STRING:
+                       if (vp->attribute == PW_NAS_PORT_ID)
+                               a = vp->strvalue;
+                       else {
+                               buf[0] = '"';
+                               librad_safeprint(vp->strvalue, vp->length,
+                                       buf + 1, sizeof(buf) - 2);
+                               strcat(buf, "\"");
+                               a = buf;
+                       }
+                       break;
+               case PW_TYPE_INTEGER:
+                       if ((v = dict_valbyattr(vp->attribute, vp->lvalue))
+                           != NULL)
+                               a = v->name;
+                       else {
+                               sprintf(buf, "%d", vp->lvalue);
+                               a = buf;
+                       }
+                       break;
+               case PW_TYPE_DATE:
+                       t = vp->lvalue;
+                       strftime(buf, sizeof(buf), "\"%b %e %Y\"",
+                               gmtime(&t));
+                       a = buf;
+                       break;
+               case PW_TYPE_IPADDR:
+                       if (vp->strvalue[0])
+                               a = vp->strvalue;
+                       else
+                               a = ip_ntoa(NULL, vp->lvalue);
+                       break;
+               default:
+                       a = "UNKNOWN";
+                       break;
+       }
+       strncpy(out, a, outlen);
+       out[outlen - 1] = 0;
+}
+
+
+/*
+ *     Print one attribute and value.
+ */
+void vp_print(FILE *fp, VALUE_PAIR *vp)
+{
+       char    buf[1024];
+
+       vp_prints(buf, sizeof(buf), vp);
+       fputs(buf, fp);
+}
+
+
+/*
+ *     Print a whole list of attributes, indented by a TAB
+ *     and with a newline at the end.
+ */
+void vp_printlist(FILE *fp, VALUE_PAIR *vp)
+{
+       for (; vp; vp = vp->next) {
+               fprintf(fp, "\t");
+               vp_print(fp, vp);
+               fprintf(fp, "\n");
+       }
+}
+
diff --git a/src/lib/radius.c b/src/lib/radius.c
new file mode 100644 (file)
index 0000000..3bd94d0
--- /dev/null
@@ -0,0 +1,703 @@
+/*
+ * radius.c    Functions to send/receive radius packets.
+ *
+ * Version:    @(#)radius.c  2.35  19-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+char radius_sccsid[] =
+"@(#)radius.c  2.35 Copyright 1998-1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+#include       <arpa/inet.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <unistd.h>
+#include       <fcntl.h>
+#include       <string.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <errno.h>
+
+#include       "libradius.h"
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#define PACKET_DATA_LEN 1600
+
+/*
+ *     Reply to the request.  Also attach
+ *     reply attribute value pairs and any user message provided.
+ */
+int rad_send(RADIUS_PACKET *packet, int activefd, char *secret)
+{
+       VALUE_PAIR              *reply;
+       UINT4                   lvalue;
+       struct  sockaddr        saremote;
+       struct  sockaddr_in     *sin;
+       int                     send_buffer[PACKET_DATA_LEN / sizeof(int)];
+       int                     len;
+       int                     secretlen;
+       int                     vendorcode, vendorpec;
+       u_short                 total_length, tmp;
+       u_char                  *hdr, *ptr, *length_ptr;
+       u_char                  digest[16];
+       char                    *what;
+
+       hdr = (u_char *)send_buffer;
+       reply = packet->vps;
+
+       switch (packet->code) {
+               case PW_PASSWORD_REJECT:
+               case PW_AUTHENTICATION_REJECT:
+                       what = "Reject";
+                       break;
+               case PW_ACCESS_CHALLENGE:
+                       what = "Challenge";
+                       break;
+               case PW_AUTHENTICATION_ACK:
+                       what = "Ack";
+                       break;
+               case PW_ACCOUNTING_RESPONSE:
+                       what = "Accounting Ack";
+                       break;
+               case PW_AUTHENTICATION_REQUEST:
+                       what = "Authentication request";
+                       break;
+               case PW_ACCOUNTING_REQUEST:
+                       what = "Accounting request";
+                       break;
+               default:
+                       what = "Reply";
+                       break;
+       }
+
+       /*
+        *      Build standard header
+        */
+       hdr[0] = packet->code;
+       hdr[1] = packet->id;
+       if (packet->code == PW_ACCOUNTING_REQUEST)
+               memset(hdr + 4, 0, AUTH_VECTOR_LEN);
+       else
+               memcpy(hdr + 4, packet->vector, AUTH_VECTOR_LEN);
+
+       DEBUG("Sending %s of id %d to %s\n",
+               what, packet->id,
+               inet_ntoa(*(struct in_addr *)&packet->dst_ipaddr));
+
+       total_length = 20;
+
+       /*
+        *      Load up the configuration values for the user
+        */
+       ptr = hdr + 20;
+       while (reply != NULL) {
+               debug_pair(reply);
+
+               /*
+                *      This could be a vendor-specific attribute.
+                */
+               length_ptr = NULL;
+               if ((vendorcode = VENDOR(reply->attribute)) > 0 &&
+                   (vendorpec  = dict_vendorpec(vendorcode)) > 0) {
+                       *ptr++ = PW_VENDOR_SPECIFIC;
+                       length_ptr = ptr;
+                       *ptr++ = 6;
+                       lvalue = htonl(vendorpec);
+                       memcpy(ptr, &lvalue, 4);
+                       ptr += 4;
+                       total_length += 6;
+               } else if (reply->attribute > 0xff) {
+                       /*
+                        *      Ignore attributes > 0xff
+                        */
+                       reply = reply->next;
+                       continue;
+               } else
+                       vendorpec = 0;
+
+#ifdef ATTRIB_NMC
+               if (vendorpec == VENDORPEC_USR) {
+                       lvalue = htonl(reply->attribute & 0xFFFF);
+                       memcpy(ptr, &lvalue, 4);
+                       total_length += 2;
+                       *length_ptr  += 2;
+                       ptr          += 4;
+               } else
+#endif
+               *ptr++ = (reply->attribute & 0xFF);
+
+               switch(reply->type) {
+
+               case PW_TYPE_STRING:
+                       /*
+                        *      FIXME: this is just to make sure but
+                        *      should NOT be needed. In fact I have no
+                        *      idea if it is needed :)
+                        */
+                       if (reply->length == 0 && reply->strvalue[0] != 0)
+                               reply->length = strlen(reply->strvalue);
+
+                       len = reply->length;
+                       if (len >= MAX_STRING_LEN) {
+                               len = MAX_STRING_LEN - 1;
+                       }
+#ifdef ATTRIB_NMC
+                       if (vendorpec != VENDORPEC_USR)
+#endif
+                               *ptr++ = len + 2;
+                       if (length_ptr) *length_ptr += len + 2;
+                       memcpy(ptr, reply->strvalue,len);
+                       ptr += len;
+                       total_length += len + 2;
+                       break;
+
+               case PW_TYPE_INTEGER:
+               case PW_TYPE_IPADDR:
+#ifdef ATTRIB_NMC
+                       if (vendorpec != VENDORPEC_USR)
+#endif
+                               *ptr++ = sizeof(UINT4) + 2;
+                       if (length_ptr) *length_ptr += sizeof(UINT4)+ 2;
+                       if (reply->type != PW_TYPE_IPADDR)
+                               lvalue = htonl(reply->lvalue);
+                       else
+                               lvalue = reply->lvalue;
+                       memcpy(ptr, &lvalue, sizeof(UINT4));
+                       ptr += sizeof(UINT4);
+                       total_length += sizeof(UINT4) + 2;
+                       break;
+
+               default:
+                       break;
+               }
+
+               reply = reply->next;
+       }
+
+       tmp = htons(total_length);
+       memcpy(hdr + 2, &tmp, sizeof(u_short));
+
+       /*
+        *      If this is not an authentication request, we
+        *      need to calculate the md5 hash over the entire packet
+        *      and put it in the vector.
+        */
+       if (packet->code != PW_AUTHENTICATION_REQUEST) {
+               secretlen = strlen(secret);
+               memcpy((char *)send_buffer + total_length, secret, secretlen);
+               librad_md5_calc(digest, (char *)send_buffer,
+                       total_length + secretlen);
+               memcpy(hdr + 4, digest, AUTH_VECTOR_LEN);
+               memset((char *)send_buffer + total_length, 0, secretlen);
+       }
+
+       /*
+        *      And send it on it's way.
+        */
+       sin = (struct sockaddr_in *) &saremote;
+        memset ((char *) sin, '\0', sizeof (saremote));
+       sin->sin_family = AF_INET;
+       sin->sin_addr.s_addr = packet->dst_ipaddr;
+       sin->sin_port = htons(packet->dst_port);
+
+       sendto(activefd, (char *)send_buffer, (int)total_length, 0,
+                       &saremote, sizeof(struct sockaddr_in));
+
+       return 0;
+}
+
+
+/*
+ *     Validates the requesting client NAS.  Calculates the
+ *     signature based on the clients private key.
+ */
+int calc_acctdigest(RADIUS_PACKET *packet, char *secret, char *recvbuf, int len)
+{
+       int             secretlen;
+       char            digest[AUTH_VECTOR_LEN];
+
+       /*
+        *      Older clients have the authentication vector set to
+        *      all zeros. Return `1' in that case.
+        */
+       memset(digest, 0, sizeof(digest));
+       if (memcmp(packet->vector, digest, AUTH_VECTOR_LEN) == 0) {
+               packet->verified = 1;
+               return 1;
+       }
+
+       /*
+        *      Zero out the auth_vector in the received packet.
+        *      Then append the shared secret to the received packet,
+        *      and calculate the MD5 sum. This must be the same
+        *      as the original MD5 sum (packet->vector).
+        */
+       secretlen = strlen(secret);
+       memset(recvbuf + 4, 0, AUTH_VECTOR_LEN);
+       memcpy(recvbuf + len, secret, secretlen);
+       librad_md5_calc(digest, recvbuf, len + secretlen);
+
+       /*
+        *      Return 0 if OK, 2 if not OK.
+        */
+       packet->verified =
+       memcmp(digest, packet->vector, AUTH_VECTOR_LEN) ? 2 : 0;
+
+       return packet->verified;
+}
+
+/*
+ *     Receive UDP client requests, and fill in
+ *     the basics of a RADIUS_PACKET structure.
+ */
+RADIUS_PACKET *rad_recv(int fd)
+{
+       RADIUS_PACKET           *packet;
+       struct sockaddr_in      saremote;
+       int                     totallen;
+       int                     salen;
+       u_char                  *hdr;
+       u_short                 len;
+
+       /*
+        *      Allocate the new request data structure
+        */
+       if ((packet = malloc(sizeof(RADIUS_PACKET))) == NULL) {
+               librad_log("out of memory");
+               errno = ENOMEM;
+               return NULL;
+       }
+       memset(packet, 0, sizeof(RADIUS_PACKET));
+       if ((packet->data = malloc(PACKET_DATA_LEN)) == NULL) {
+               free(packet);
+               librad_log("out of memory");
+               errno = ENOMEM;
+               return NULL;
+       }
+
+       /*
+        *      Receive the packet.
+        */
+       salen = sizeof(saremote);
+       packet->data_len = recvfrom(fd, packet->data, PACKET_DATA_LEN,
+               0, (struct sockaddr *)&saremote, &salen);
+       if (packet->data_len < 20) return NULL;
+
+       hdr = (u_char *)packet->data;
+       memcpy(&len, hdr + 2, sizeof(u_short));
+       totallen = ntohs(len);
+       if (packet->data_len > totallen) packet->data_len = totallen;
+
+       DEBUG("rad_recv: Packet from host %s code=%d, id=%d, length=%d\n",
+                       inet_ntoa(saremote.sin_addr),
+                       hdr[0], hdr[1], totallen);
+
+       /*
+        *      Fill header fields
+        */
+       packet->src_ipaddr = saremote.sin_addr.s_addr;
+       packet->src_port = ntohs(saremote.sin_port);
+       packet->code = hdr[0];
+       packet->id = hdr[1];
+       memcpy(packet->vector, hdr + 4, AUTH_VECTOR_LEN);
+
+       return packet;
+}
+
+/*
+ *     Calculate/check digest, and decode radius attributes.
+ */
+int rad_decode(RADIUS_PACKET *packet, char *secret)
+{
+       DICT_ATTR               *attr;
+       UINT4                   lvalue;
+       UINT4                   vendorcode;
+       UINT4                   vendorpec;
+       VALUE_PAIR              *first_pair;
+       VALUE_PAIR              *prev;
+       VALUE_PAIR              *pair;
+       u_char                  *hdr, *ptr;
+       int                     length;
+       int                     attribute;
+       int                     attrlen;
+       int                     vendorlen;
+
+       hdr = (u_char *)packet->data;
+       length = packet->data_len;
+
+       /*
+        *      Calculate and/or verify digest.
+        */
+       switch(packet->code) {
+               case PW_AUTHENTICATION_REQUEST:
+                       break;
+               case PW_ACCOUNTING_REQUEST:
+                       if (calc_acctdigest(packet, secret,
+                           packet->data, length) > 1) {
+                               librad_log("Received accounting packet "
+                                   "from %s with invalid signature!",
+                                   inet_ntoa(*(struct in_addr*)&(packet->src_ipaddr)));
+                               return 1;
+                       }
+                       break;
+               case PW_AUTHENTICATION_ACK:
+               case PW_AUTHENTICATION_REJECT:
+               case PW_ACCOUNTING_RESPONSE:
+                       /*
+                        *      Answers from remote radius servers.
+                        *      Need to verify the answer.
+                        *      FIXME: actually do that here !!!
+                        */
+                       break;
+       }
+
+       /*
+        *      Extract attribute-value pairs
+        */
+       ptr = hdr + 20;
+       length -= AUTH_HDR_LEN;
+       first_pair = NULL;
+       prev = NULL;
+
+       vendorcode = 0;
+       vendorlen  = 0;
+
+       while(length > 0) {
+
+               if (vendorlen > 0) {
+                       attribute = *ptr++ | (vendorcode << 16);
+                       attrlen   = *ptr++;
+               } else {
+                       attribute = *ptr++;
+                       attrlen   = *ptr++;
+               }
+               if (attrlen < 2) {
+                       length = 0;
+                       continue;
+               }
+               attrlen -= 2;
+               length  -= 2;
+
+               /*
+                *      This could be a Vendor-Specific attribute.
+                *
+                */
+               if (vendorlen <= 0 &&
+                   attribute == PW_VENDOR_SPECIFIC && attrlen > 6) {
+                       memcpy(&lvalue, ptr, 4);
+                       vendorpec = ntohl(lvalue);
+                       if ((vendorcode = dict_vendorcode(vendorpec))
+                           != 0) {
+#ifdef ATTRIB_NMC
+                               if (vendorpec == VENDORPEC_USR) {
+                                       ptr += 4;
+                                       memcpy(&lvalue, ptr, 4);
+                                       /*printf("received USR %04x\n", ntohl(lvalue));*/
+                                       attribute = (ntohl(lvalue) & 0xFFFF) |
+                                                       (vendorcode << 16);
+                                       ptr += 4;
+                                       attrlen -= 8;
+                                       length -= 8;
+                               } else
+#endif
+                               {
+                                       ptr += 4;
+                                       vendorlen = attrlen - 4;
+                                       attribute = *ptr++ | (vendorcode << 16);
+                                       attrlen   = *ptr++;
+                                       attrlen -= 2;
+                                       length -= 6;
+                               }
+                       }
+               }
+
+               if ( attrlen >= MAX_STRING_LEN ) {
+                       DEBUG("attribute %d too long, %d >= %d\n", attribute,
+                               attrlen, MAX_STRING_LEN);
+               }
+               else if ( attrlen > length ) {
+                       DEBUG("attribute %d longer as buffer left, %d > %d\n",
+                               attribute, attrlen, length);
+               }
+               else {
+                       /*
+                        *      FIXME: should we us paircreate() ?
+                        */
+                       if ((pair = malloc(sizeof(VALUE_PAIR))) == NULL) {
+                               pairfree(first_pair);
+                               librad_log("out of memory");
+                               errno = ENOMEM;
+                               return -1;
+                       }
+                       memset(pair, 0, sizeof(VALUE_PAIR));
+                       if ((attr = dict_attrbyvalue(attribute)) == NULL) {
+                               sprintf(pair->name, "Attr-%d", attribute);
+                               pair->type = PW_TYPE_STRING;
+                       } else {
+                               strcpy(pair->name, attr->name);
+                               pair->type = attr->type;
+                       }
+                       pair->attribute = attribute;
+                       pair->length = attrlen;
+                       pair->next = NULL;
+
+                       switch (attr->type) {
+
+                       case PW_TYPE_STRING:
+                               /* attrlen always < MAX_STRING_LEN */
+                               memcpy(pair->strvalue, ptr, attrlen);
+                               debug_pair(pair);
+                               if (first_pair == NULL)
+                                       first_pair = pair;
+                               else
+                                       prev->next = pair;
+                               prev = pair;
+                               break;
+                       
+                       case PW_TYPE_INTEGER:
+                       case PW_TYPE_DATE:
+                       case PW_TYPE_IPADDR:
+                               memcpy(&lvalue, ptr, sizeof(UINT4));
+                               if (attr->type != PW_TYPE_IPADDR)
+                                       pair->lvalue = ntohl(lvalue);
+                               else
+                                       pair->lvalue = lvalue;
+                               debug_pair(pair);
+                               if (first_pair == NULL)
+                                       first_pair = pair;
+                               else
+                                       prev->next = pair;
+                               prev = pair;
+                               break;
+                       
+                       default:
+                               DEBUG("    %s (Unknown Type %d)\n",
+                                       attr->name,attr->type);
+                               free(pair);
+                               break;
+                       }
+
+               }
+               ptr += attrlen;
+               length -= attrlen;
+               if (vendorlen > 0) vendorlen -= (attrlen + 2);
+       }
+
+       packet->vps = first_pair;
+
+       free(packet->data);
+       packet->data = NULL;
+       packet->data_len = 0;
+
+       return 0;
+}
+
+
+/*
+ *     Encode password.
+ *
+ *     We assume that the passwd buffer passed is big enough.
+ *     RFC2138 says the password is max 128 chars, so the size
+ *     of the passwd buffer must be at least 129 characters.
+ *     Preferably it's just MAX_STRING_LEN.
+ *
+ *     int *pwlen is updated to the new length of the encrypted
+ *     password - a multiple of 16 bytes.
+ */
+int rad_pwencode(char *passwd, int *pwlen, char *secret, char *vector)
+{
+       u_char  buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 1];
+       char    digest[AUTH_VECTOR_LEN];
+       int     i, n, secretlen;
+       int     len;
+
+       /*
+        *      Padd password to multiple of 16 bytes.
+        */
+       len = strlen(passwd);
+       if (len > 128) len = 128;
+       *pwlen = len;
+       if (len % 16 != 0) {
+               n = 16 - (len % 16);
+               for (i = len; n > 0; n--, i++)
+                       passwd[i] = 0;
+               len = *pwlen = i;
+       }
+
+       /*
+        *      Use the secret to setup the decryption digest
+        */
+       secretlen = strlen(secret);
+       strcpy(buffer, secret);
+       memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
+       librad_md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN);
+
+       /*
+        *      Now we can encode the password *in place*
+        */
+       for (i = 0; i < 16; i++)
+               passwd[i] ^= digest[i];
+
+       if (len <= 16) return 0;
+
+       /*
+        *      Length > 16, so we need to use the extended
+        *      algorithm.
+        */
+       for (n = 0; n < 128 && n <= (len - 16); n += 16) { 
+               memcpy(buffer + secretlen, passwd + n, 16);
+               librad_md5_calc(digest, buffer, secretlen + 16);
+               for (i = 0; i < 16; i++)
+                       passwd[i + n + 16] ^= digest[i];
+       }
+
+       return 0;
+}
+
+/*
+ *     Decode password.
+ */
+int rad_pwdecode(char *passwd, int pwlen, char *secret, char *vector)
+{
+       u_char  buffer[AUTH_VECTOR_LEN + MAX_STRING_LEN + 1];
+       char    digest[AUTH_VECTOR_LEN];
+       char    r[AUTH_VECTOR_LEN];
+       char    *s;
+       int     i, n, secretlen;
+       int     rlen;
+
+       /*
+        *      Use the secret to setup the decryption digest
+        */
+       secretlen = strlen(secret);
+       strcpy(buffer, secret);
+       memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN);
+       librad_md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN);
+
+       /*
+        *      Now we can decode the password *in place*
+        */
+       memcpy(r, passwd, 16);
+       for (i = 0; i < 16 && i < pwlen; i++)
+               passwd[i] ^= digest[i];
+
+       if (pwlen <= 16) {
+               passwd[i] = 0;
+               return 0;
+       }
+
+       /*
+        *      Length > 16, so we need to use the extended
+        *      algorithm.
+        */
+       rlen = ((pwlen - 1) / 16) * 16;
+
+       for (n = rlen; n > 0; n -= 16 ) { 
+               s = (n == 16) ? r : (passwd + n - 16);
+               memcpy(buffer + secretlen, s, 16);
+               librad_md5_calc(digest, buffer, secretlen + 16);
+               for (i = 0; i < 16 && (i + n) < pwlen; i++)
+                       passwd[i + n] ^= digest[i];
+       }
+       passwd[pwlen] = 0;
+
+       return 0;
+}
+
+/*
+ *     Create a random vector of AUTH_VECTOR_LEN bytes.
+ */
+static void random_vector(char *vector)
+{
+       int             randno;
+       int             i;
+       static int      did_srand = 0;
+#ifdef __linux__
+       static int      urandom_fd = -1;
+#endif
+
+#ifdef __linux__
+       /*
+        *      Use /dev/urandom if available.
+        */
+       if (urandom_fd > -2) {
+               /*
+                *      Open urandom fd if not yet opened.
+                */
+               if (urandom_fd < 0)
+                       urandom_fd = open("/dev/urandom", O_RDONLY);
+               if (urandom_fd < 0) {
+                       /*
+                        *      It's not there, don't try
+                        *      it again.
+                        */
+                       DEBUG("Cannot open /dev/urandom, using rand()\n");
+                       urandom_fd = -2;
+               } else {
+
+                       fcntl(urandom_fd, F_SETFD, 1);
+
+                       /*
+                        *      Read 16 bytes.
+                        */
+                       if (read(urandom_fd, vector, AUTH_VECTOR_LEN)
+                           == AUTH_VECTOR_LEN)
+                               return;
+                       /*
+                        *      We didn't get 16 bytes - fall
+                        *      back on rand) and don't try again.
+                        */
+               DEBUG("Read short packet from /dev/urandom, using rand()\n");
+                       urandom_fd = -2;
+               }
+       }
+#endif
+
+       if (!did_srand) {
+               srand(time(0) + getpid());
+               did_srand = 1;
+       }
+       for (i = 0; i < AUTH_VECTOR_LEN; i += sizeof(int)) {
+               randno = rand();
+               memcpy(vector, &randno, sizeof(int));
+               vector += sizeof(int);
+       }
+}
+
+
+/*
+ *     Allocate a new RADIUS_PACKET
+ */
+RADIUS_PACKET *rad_alloc(int newvector)
+{
+       RADIUS_PACKET   *rp;
+
+       if ((rp = malloc(sizeof(RADIUS_PACKET))) == NULL)
+               return NULL;
+       memset(rp, 0, sizeof(RADIUS_PACKET));
+       if (newvector)
+               random_vector(rp->vector);
+
+       return rp;
+}
+
+/*
+ *     Free a RADIUS_PACKET
+ */
+void rad_free(RADIUS_PACKET *rp)
+{
+       if (rp->data) free(rp->data);
+       if (rp->vps) pairfree(rp->vps);
+       free(rp);
+}
+
diff --git a/src/lib/token.c b/src/lib/token.c
new file mode 100644 (file)
index 0000000..15dadb4
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * token.c     Read the next token from a string.
+ *             Yes it's pretty primitive but effective.
+ *
+ * Version:    @(#)token.c  1.00  19-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "token.h"
+
+typedef struct {
+       char *str;
+       int token;
+} TOKEN;
+
+static TOKEN tokens[] = {
+       { "{",  T_LCBRACE,      },
+       { "}",  T_RCBRACE,      },
+       { "(",  T_LBRACE,       },
+       { ")",  T_RBRACE,       },
+       { ",",  T_COMMA,        },
+       { "+=", T_OP_ADD,       },
+       { "-=", T_OP_SUB,       },
+       { ":=", T_OP_SET,       },
+       { "=",  T_OP_EQ,        },
+       { "!=", T_OP_NE,        },
+       { ">=", T_OP_GE,        },
+       { ">",  T_OP_GT,        },
+       { "<=", T_OP_LE,        },
+       { "<",  T_OP_LT,        },
+       { NULL, 0,              },
+};
+
+/*
+ *     This works only as long as special tokens
+ *     are max. 2 characters, but it's fast.
+ */
+#define TOKEN_MATCH(bptr, tptr) \
+       ( (tptr)[0] == (bptr)[0] && \
+        ((tptr)[1] == (bptr)[1] || (tptr)[1] == 0))
+
+/*
+ *     Read a word from a buffer and advance pointer.
+ *     This function knows about escapes and quotes.
+ *
+ *     At end-of-line, buf[0] is set to '\0'.
+ *     Returns 0 or special token value.
+ */
+static int getthing(char **ptr, char *buf, int buflen, int tok)
+{
+       char    *s, *p;
+       int     quote;
+       int     escape;
+       int     x;
+       TOKEN   *t;
+
+       buf[0] = 0;
+
+       /* Skip whitespace */
+       p = *ptr;
+       while (*p && isspace(*p))
+               p++;
+
+       if (*p == 0) {
+               *ptr = p;
+               return T_EOL;
+       }
+
+       /*
+        *      Might be a 1 or 2 character token.
+        */
+       if (tok) for (t = tokens; t->str; t++) {
+               if (TOKEN_MATCH(p, t->str)) {
+                       strcpy(buf, t->str);
+                       p += strlen(t->str);
+                       while (isspace(*p))
+                               p++;
+                       *ptr = p;
+                       return t->token;
+               }
+       }
+
+       /* Read word. */
+       quote = 0;
+       if (*p == '"') {
+               quote = 1;
+               p++;
+       }
+       s = buf;
+       escape = 0;
+
+       while (*p && buflen-- > 0) {
+               if (escape) {
+                       escape = 0;
+                       switch(*p) {
+                               case 'r':
+                                       *s++ = '\r';
+                                       break;
+                               case 'n':
+                                       *s++ = '\n';
+                                       break;
+                               case 't':
+                                       *s++ = '\t';
+                                       break;
+                               default:
+                                       if (*p >= '0' && *p <= '9' &&
+                                           sscanf(p, "%3o", &x) == 1) {
+                                               *s++ = x;
+                                               p += 2;
+                                       } else
+                                               *s++ = *p;
+                                       break;
+                       }
+                       p++;
+                       continue;
+               }
+               if (*p == '\\') {
+                       p++;
+                       escape = 1;
+                       continue;
+               }
+               if (quote && *p == '"') {
+                       p++;
+                       break;
+               }
+               if (!quote) {
+                       if (isspace(*p))
+                               break;
+                       if (tok) {
+                               for (t = tokens; t->str; t++)
+                                       if (TOKEN_MATCH(p, t->str))
+                                               break;
+                               if (t->str != NULL)
+                                       break;
+                       }
+               }
+               *s++ = *p++;
+       }
+       *s++ = 0;
+
+       /* Skip whitespace again. */
+       while (*p && isspace(*p))
+               p++;
+       *ptr = p;
+
+       return (buf[0]) ? 0 : T_EOL;
+}
+
+/*
+ *     Read a "word" - this means we don't honor
+ *     tokens as delimiters.
+ */
+int getword(char **ptr, char *buf, int buflen)
+{
+       return getthing(ptr, buf, buflen, 0) == T_EOL ? 0 : 1;
+}
+
+/*
+ *     Read the next word, use tokens as delimiters.
+ */
+int gettoken(char **ptr, char *buf, int buflen)
+{
+       return getthing(ptr, buf, buflen, 1);
+}
+
diff --git a/src/lib/valuepair.c b/src/lib/valuepair.c
new file mode 100644 (file)
index 0000000..ac5b589
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+ * valuepair.c Functions to handle VALUE_PAIRs
+ *
+ * Version:    @(#)valuepair.c  1.00  19-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+char valuepair_sccsid[] =
+"@(#)radius.c  1.00 Copyright 1998-1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <time.h>
+#include       <ctype.h>
+
+#include       "libradius.h"
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+
+static char *months[] = {
+        "jan", "feb", "mar", "apr", "may", "jun",
+        "jul", "aug", "sep", "oct", "nov", "dec" };
+
+
+/*
+ *     Create a new valuepair.
+ */
+VALUE_PAIR *paircreate(int attr, int type)
+{
+       VALUE_PAIR      *vp;
+       DICT_ATTR       *da;
+
+       if ((vp = malloc(sizeof(VALUE_PAIR))) == NULL)
+               return NULL;
+       memset(vp, 0, sizeof(VALUE_PAIR));
+       vp->attribute = attr;
+       vp->type = type;
+       if ((da = dict_attrbyvalue(attr)) != NULL)
+               strcpy(vp->name, da->name);
+       else
+               sprintf(vp->name, "Attr-%d", attr);
+       switch (vp->type) {
+               case PW_TYPE_INTEGER:
+               case PW_TYPE_IPADDR:
+               case PW_TYPE_DATE:
+                       vp->length = 4;
+                       break;
+               default:
+                       vp->length = 0;
+                       break;
+       }
+
+       return vp;
+}
+
+/*
+ *     Release the memory used by a list of attribute-value
+ *     pairs.
+ */
+void pairfree(VALUE_PAIR *pair)
+{
+       VALUE_PAIR      *next;
+
+       while(pair != NULL) {
+               next = pair->next;
+               free(pair);
+               pair = next;
+       }
+}
+
+
+/*
+ *     Find the pair with the mathing attribute
+ */
+VALUE_PAIR * pairfind(VALUE_PAIR *first, int attr)
+{
+       while(first && first->attribute != attr)
+               first = first->next;
+       return first;
+}
+
+
+/*
+ *     Delete the pair(s) with the mathing attribute
+ */
+void pairdelete(VALUE_PAIR **first, int attr)
+{
+       VALUE_PAIR *i, *next, *last = NULL;
+
+       for(i = *first; i; i = next) {
+               next = i->next;
+               if (i->attribute == attr) {
+                       if (last)
+                               last->next = next;
+                       else
+                               *first = next;
+                       free(i);
+               } else
+                       last = i;
+       }
+}
+
+/*
+ *     Add a pair at the end of a VALUE_PAIR list.
+ */
+void pairadd(VALUE_PAIR **first, VALUE_PAIR *new)
+{
+       VALUE_PAIR *i;
+
+       new->next = NULL;
+       if (*first == NULL) {
+               *first = new;
+               return;
+       }
+       for(i = *first; i->next; i = i->next)
+               ;
+       i->next = new;
+}
+
+/*
+ *     Copy just a certain type of pairs.
+ */
+VALUE_PAIR *paircopy2(VALUE_PAIR *vp, int attr)
+{
+       VALUE_PAIR      *first, *n, *last;
+
+       first = NULL;
+       last = NULL;
+
+       while (vp) {
+               if (attr >= 0 && vp->attribute != attr) {
+                       vp = vp->next;
+                       continue;
+               }
+               if ((n = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == NULL)
+                       return first;
+               memcpy(n, vp, sizeof(VALUE_PAIR));
+               n->next = NULL;
+               if (last == NULL)
+                       first = n;
+               else
+                       last->next = n;
+               last = n;
+               vp = vp->next;
+       }
+       return first;
+}
+
+
+/*
+ *     Copy a pairlist.
+ */
+VALUE_PAIR *paircopy(VALUE_PAIR *vp)
+{
+       return paircopy2(vp, -1);
+}
+
+
+/*
+ *     Move attributes from one list to the other
+ *     if not already present.
+ */
+void pairmove(VALUE_PAIR **to, VALUE_PAIR **from)
+{
+       VALUE_PAIR *tailto, *i, *next;
+       VALUE_PAIR *tailfrom = NULL;
+       int has_password = 0;
+
+       if (*to == NULL) {
+               *to = *from;
+               *from = NULL;
+               return;
+       }
+
+       /*
+        *      First, see if there are any passwords here, and
+        *      point "tailto" to the end of the "to" list.
+        */
+       tailto = *to;
+       for(i = *to; i; i = i->next) {
+               if (i->attribute == PW_PASSWORD ||
+               /*
+                *      FIXME: this seems to be needed with PAM support
+                *      to keep it around the Auth-Type = Pam stuff.
+                *      Perhaps we should only do this if Auth-Type = Pam?
+                */
+#ifdef WITH_PAM
+                   i->attribute == PAM_AUTH_ATTR ||
+#endif
+                   i->attribute == PW_CRYPT_PASSWORD)
+                       has_password = 1;
+               tailto = i;
+       }
+
+       /*
+        *      Loop over the "from" list.
+        */
+       for(i = *from; i; i = next) {
+               next = i->next;
+               /*
+                *      If there was a password in the "to" list,
+                *      do not move any other password from the
+                *      "from" to the "to" list.
+                */
+               if (has_password &&
+                   (i->attribute == PW_PASSWORD ||
+#ifdef WITH_PAM
+                    i->attribute == PAM_AUTH_ATTR ||
+#endif
+                    i->attribute == PW_CRYPT_PASSWORD)) {
+                       tailfrom = i;
+                       continue;
+               }
+               /*
+                *      If the attribute is already present in "to",
+                *      do not move it from "from" to "to". We make
+                *      an exception for "Hint" which can appear multiple
+                *      times, and we never move "Fall-Through".
+                */
+               if (i->attribute == PW_FALL_THROUGH ||
+                   (i->attribute != PW_HINT && i->attribute != PW_FRAMED_ROUTE
+                    && pairfind(*to, i->attribute) != 0)) {
+                       tailfrom = i;
+                       continue;
+               }
+               if (tailfrom)
+                       tailfrom->next = next;
+               else
+                       *from = next;
+               tailto->next = i;
+               i->next = NULL;
+               tailto = i;
+       }
+}
+
+/*
+ *     Move one kind of attributes from one list to the other
+ */
+void pairmove2(VALUE_PAIR **to, VALUE_PAIR **from, int attr)
+{
+       VALUE_PAIR *to_tail, *i, *next;
+       VALUE_PAIR *iprev = NULL;
+
+       /*
+        *      Find the last pair in the "to" list and put it in "to_tail".
+        */
+       if (*to != NULL) {
+               to_tail = *to;
+               for(i = *to; i; i = i->next)
+                       to_tail = i;
+       } else
+               to_tail = NULL;
+
+       for(i = *from; i; i = next) {
+               next = i->next;
+
+               if (i->attribute != attr) {
+                       iprev = i;
+                       continue;
+               }
+
+               /*
+                *      Remove the attribute from the "from" list.
+                */
+               if (iprev)
+                       iprev->next = next;
+               else
+                       *from = next;
+
+               /*
+                *      Add the attribute to the "to" list.
+                */
+               if (to_tail)
+                       to_tail->next = i;
+               else
+                       *to = i;
+               to_tail = i;
+               i->next = NULL;
+       }
+}
+
+
+/*
+ *     Sort of strtok/strsep function.
+ */
+static char *mystrtok(char **ptr, char *sep)
+{
+       char    *res;
+
+       if (**ptr == 0)
+               return NULL;
+       while (**ptr && strchr(sep, **ptr))
+               (*ptr)++;
+       if (**ptr == 0)
+               return NULL;
+       res = *ptr;
+       while (**ptr && strchr(sep, **ptr) == NULL)
+               (*ptr)++;
+       if (**ptr != 0)
+               *(*ptr)++ = 0;
+       return res;
+}
+
+/*
+ *     Turn printable string into time_t
+ */
+static time_t gettime(char *valstr)
+{
+       int             i;
+       time_t          t;
+       struct tm       *tm;
+       char            buf[32];
+       char            *p;
+       char            *y, *m, *d;
+
+       time(&t);
+       tm = localtime(&t);
+
+       strncpy(buf, valstr, sizeof(buf));
+       buf[sizeof(buf) - 1] = 0;
+       for (p = buf; *p; p++)
+               if (isupper(*p)) *p = tolower(*p);
+
+       p = buf;
+       y = mystrtok(&p, " \t");
+       m = mystrtok(&p, " \t");
+       d = mystrtok(&p, " \t");
+       if (!y || !m || !d) return 0;
+
+       for (i = 0; i < 12; i++) {
+               if (strncmp(months[i], y, 3) == 0) {
+                       tm->tm_mon = i;
+                       i = 13;
+               }
+       }
+       tm->tm_mday = atoi(m);
+       tm->tm_year = atoi(y);
+       if (tm->tm_year >= 1900) tm->tm_year -= 1900;
+
+       return mktime(tm);
+}
+
+/*
+ *     Create a VALUE_PAIR from an ASCII attribute and value.
+ */
+static VALUE_PAIR *pairmake(char *attribute, char *value, int operator)
+{
+       DICT_ATTR       *da;
+       DICT_VALUE      *dval;
+       VALUE_PAIR      *vp;
+       char            *p, *s;
+
+       if ((da = dict_attrbyname(attribute)) == NULL)
+               return NULL;
+
+       if ((vp = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == NULL)
+               return NULL;
+
+       memset(vp, 0, sizeof(VALUE_PAIR));
+       vp->attribute = da->attr;
+       vp->type = da->type;
+       vp->operator = (operator == 0) ? T_OP_EQ : operator;
+       strcpy(vp->name, da->name);
+
+       /*
+        *      Even for integers, dates and ip addresses we
+        *      keep the original string in vp->strvalue.
+        */
+       strncpy(vp->strvalue, value, MAX_STRING_LEN);
+       vp->strvalue[MAX_STRING_LEN - 1] = 0;
+
+       switch(da->type) {
+               case PW_TYPE_STRING:
+                       vp->length = strlen(value);
+                       break;
+               case PW_TYPE_IPADDR:
+                       /*
+                        *      FIXME: complain if hostname
+                        *      cannot be resolved, or resolve later!
+                        */
+                       if ((p = strrchr(value, '+')) != NULL && !p[1]) {
+                               *p = 0;
+                               vp->addport = 1;
+                       } else
+                               p = NULL;
+                       vp->lvalue = librad_dodns ? ip_getaddr(value) :
+                                                   ip_addr(value);
+                       vp->length = 4;
+                       if (p) *p = '+';
+                       break;
+               case PW_TYPE_INTEGER:
+                       /*
+                        *      For PW_NAS_PORT_ID, allow a
+                        *      port range instead of just a port.
+                        */
+                       if (vp->attribute == PW_NAS_PORT_ID) {
+                               for(s = value; *s; s++)
+                                       if (!isdigit(*s)) break;
+                               if (*s) {
+                                       vp->type = PW_TYPE_STRING;
+                                       vp->length = strlen(value);
+                                       break;
+                               }
+                       }
+                       if (isdigit(*value)) {
+                               vp->lvalue = atoi(value);
+                               vp->length = 4;
+                       }
+                       else if ((dval = dict_valbyname(value)) == NULL) {
+                               free(vp);
+                               librad_log("unknown value %s", value);
+                               return NULL;
+                       }
+                       else {
+                               vp->lvalue = dval->value;
+                               vp->length = 4;
+                       }
+                       break;
+
+               case PW_TYPE_DATE:
+                       if ((vp->lvalue = gettime(value)) == (time_t)-1) {
+                               free(vp);
+                               return NULL;
+                       }
+                       vp->length = 4;
+                       break;
+               default:
+                       free(vp);
+                       return NULL;
+       }
+       return vp;
+}
+
+/*
+ *     Read a valuepair from a buffer, and advance pointer.
+ *     Sets *eol to 1 if end of line was encountered.
+ */
+VALUE_PAIR *pairread(char **ptr, int *eol)
+{
+       char            buf[64];
+       char            attr[64];
+       char            value[256];
+       char            *p;
+       int             token, t;
+
+       *eol = 0;
+
+       /* Get attribute. */
+       gettoken(ptr, attr, sizeof(attr));
+       if (attr[0] == 0)
+               return NULL;
+
+       /* Now we should have an '=' here. */
+       token = gettoken(ptr, buf, sizeof(buf));
+       if (token < T_EQSTART || token > T_EQEND)
+               return NULL;
+
+       /* Read value. */
+       gettoken(ptr, value, sizeof(value));
+       if (value[0] == 0)
+               return NULL;
+
+       /*
+        *      Peek at the next token. Must be T_EOL or T_COMMA.
+        */
+       p = *ptr;
+       t = gettoken(&p, buf, sizeof(buf));
+       if (t != T_EOL && t != T_COMMA)
+               return NULL;
+
+       if (t == T_COMMA) {
+               *ptr = p;
+               /*
+                *      HACK: should peek again, taking shortcut :)
+                */
+               if (*p == 0)
+                       *eol = 1;
+       } else
+               *eol = 1;
+
+       return pairmake(attr, value, token);
+}
+
+/*
+ *     Read one line of attribute/value pairs. This might contain
+ *     multiple pairs seperated by comma's.
+ */
+int userparse(char *buffer, VALUE_PAIR **first_pair)
+{
+       VALUE_PAIR      *vp;
+       char            *p;
+       int             eol = 0;
+
+       /*
+        *      We allow an empty line.
+        */
+       if (buffer[0] == 0)
+               return 0;
+
+       p = buffer;
+       do {
+               if ((vp = pairread(&p, &eol)) == NULL)
+                       return -1;
+               pairadd(first_pair, vp);
+       } while (!eol);
+
+       return 0;
+}
+
diff --git a/src/main/00-OLD/Make.inc b/src/main/00-OLD/Make.inc
new file mode 100644 (file)
index 0000000..44defb7
--- /dev/null
@@ -0,0 +1,117 @@
+#
+# Makefile     RADIUS - 
+#              Remote Authentication Dial In User Service
+#
+#
+
+SERVER_OBJS    = radiusd.o dict.o files.o util.o md5.o attrprint.o \
+                       acct.o radius.o pam.o log.o version.o proxy.o \
+                       exec.o auth.o timestr.o cache.o
+SERVERDBM_OBJS = radiusddbm.o dict.o filesdbm.o util.o md5.o attrprint.o \
+                       acct.o radius.o pam.o log.o versiondbm.o proxy.o \
+                       exec.o auth.o timestr.o cache.o
+SERVER_SRCS    = radiusd.c dict.c files.c util.c md5.c attrprint.c acct.c \
+                       radius.c pam.c log.c version.c proxy.c \
+                       exec.c auth.c timestr.c cache.c
+INCLUDES       = radius.h conf.h
+
+all:   radiusd radwho radzap raduse radtest
+
+dbm:   radiusd.dbm builddbm
+
+radiusd: $(SERVER_OBJS)
+       $(CC) $(LDFLAGS) -o radiusd $(SERVER_OBJS) $(LIBS) $(LCRYPT) $(PAMLIB)
+
+radiusd.dbm: $(SERVERDBM_OBJS)
+       $(CC) $(LDFLAGS) -o radiusd.dbm $(SERVERDBM_OBJS) $(LIBS) $(LCRYPT) \
+                        $(DBMLIB) $(PAMLIB)
+
+radiusd.o: radiusd.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c radiusd.c
+
+radiusddbm.o: radiusd.c $(INCLUDES)
+       $(CC) $(CFLAGS) $(DBM) -c radiusd.c -o radiusddbm.o
+
+acct.o: acct.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c acct.c
+
+attrprint.o: attrprint.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c attrprint.c
+
+dict.o: dict.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c dict.c
+
+files.o: files.c $(INCLUDES)
+       $(CC) $(CFLAGS) $(PAM) -c files.c
+
+filesdbm.o: files.c $(INCLUDES)
+       $(CC) $(CFLAGS) $(DBM) $(PAM) -o filesdbm.o -c files.c
+
+radius.o: radius.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c radius.c
+
+util.o: util.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c util.c
+
+pam.o:  pam.c $(INCLUDES)
+       $(CC) $(CFLAGS) $(PAM) -c pam.c
+
+cache.o:  cache.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c cache.c 
+
+proxy.o:  proxy.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c proxy.c
+
+exec.o:  exec.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c exec.c
+
+auth.o:  auth.c $(INCLUDES)
+       $(CC) $(CFLAGS) $(PAM) -c auth.c
+
+version.o: version.c $(INCLUDES)
+       $(CC) $(CFLAGS) -o version.o -c version.c
+
+versiondbm.o: version.c $(INCLUDES)
+       $(CC) $(CFLAGS) $(DBM) -o versiondbm.o -c version.c
+
+radtest: radtest.o md5.o util.o dict.o attrprint.o log.o
+       $(CC) $(LDFLAGS) -o radtest radtest.o md5.o util.o \
+               dict.o attrprint.o log.o $(LIBS)
+
+radtest.o: radtest.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c radtest.c
+
+md5.o: md5.c md5.h
+       $(CC) $(CFLAGS) -c md5.c
+
+builddbm: builddbm.o
+       $(CC) $(LDFLAGS) -o builddbm builddbm.o $(DBMLIB) $(LIBS)
+
+builddbm.o: builddbm.c
+       $(CC) $(CFLAGS) -c $(DBM) builddbm.c
+
+radwho: radwho.o util.o
+       $(CC) $(LDFLAGS) -o radwho radwho.o util.o $(LIBS)
+
+raduse: raduse.o
+       $(CC) $(LDFLAGS) -o raduse raduse.o $(LIBS)
+
+radzap: radzap.o util.o
+       $(CC) $(LDFLAGS) -o radzap radzap.o util.o $(LIBS)
+
+lint:
+       -lint -hbacvx -DLINT $(SERVER_SRCS)
+       -lint -hbacvx -DLINT ../radpass.c ../md5.c ../util.c
+
+clean:
+       rm -f *.o radiusd radwho raduse radtest radzap builddbm radiusd.dbm
+       rm -f ../build ../debian/substvars ../debian/files
+
+install:
+       install -m 755 -s radiusd $(SBINDIR)/radiusd
+       install -m 755 -s radwho  $(BINDIR)
+       install -m 755 -s raduse  $(BINDIR)
+       install -m 755 -s radzap  $(BINDIR)
+       install -m 755    checkrad.pl $(SBINDIR)/checkrad
+       install -m 755    radlast $(BINDIR)
+
diff --git a/src/main/00-OLD/Makefile b/src/main/00-OLD/Makefile
new file mode 100644 (file)
index 0000000..47ff6d2
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Makefile     Radius Makefile for Linux (2.0.x, lib5 or libc6)
+#
+#
+
+#
+#      Autoselect -lshadow and -lcrypt
+#
+ifneq ($(wildcard /usr/lib/libshadow.a),)
+LSHADOW        = -lshadow
+endif
+ifneq ($(wildcard /usr/lib/libcrypt.a),)
+LCRYPT = -lcrypt
+endif
+
+CC     = gcc
+CFLAGS = -Wall -g # -DNOSHADOW
+LDFLAGS        = # -s # tatic
+LIBS   = $(LSHADOW)
+
+DBM    = -DNDBM
+DBMLIB = -ldb
+
+# Uncomment these if you want PAM support
+#PAM   = -DPAM
+#PAMLIB        = -lpam -ldl
+
+BINDIR  = /usr/local/bin
+SBINDIR = /usr/local/sbin
+
+include Make.inc
diff --git a/src/main/00-OLD/Makefile.BSD b/src/main/00-OLD/Makefile.BSD
new file mode 100644 (file)
index 0000000..900c5e4
--- /dev/null
@@ -0,0 +1,21 @@
+#
+# Makefile     Radius Makefile for BSD (FreeBSD, NetBSD, etc)
+#
+#
+
+CC     = gcc
+CFLAGS = -Wall -g -DNOSHADOW
+LDFLAGS        = # -s #tatic
+LIBS   =
+LCRYPT = -lcrypt
+
+DBM     = -DNDBM
+DBMLIB  = #-ldb
+
+#PAM   = -DPAM
+#PAMLIB        = -lpam
+
+BINDIR  = /usr/local/bin
+SBINDIR = /usr/local/sbin
+
+.include "Make.inc"
diff --git a/src/main/00-OLD/Makefile.lnx b/src/main/00-OLD/Makefile.lnx
new file mode 100644 (file)
index 0000000..47ff6d2
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Makefile     Radius Makefile for Linux (2.0.x, lib5 or libc6)
+#
+#
+
+#
+#      Autoselect -lshadow and -lcrypt
+#
+ifneq ($(wildcard /usr/lib/libshadow.a),)
+LSHADOW        = -lshadow
+endif
+ifneq ($(wildcard /usr/lib/libcrypt.a),)
+LCRYPT = -lcrypt
+endif
+
+CC     = gcc
+CFLAGS = -Wall -g # -DNOSHADOW
+LDFLAGS        = # -s # tatic
+LIBS   = $(LSHADOW)
+
+DBM    = -DNDBM
+DBMLIB = -ldb
+
+# Uncomment these if you want PAM support
+#PAM   = -DPAM
+#PAMLIB        = -lpam -ldl
+
+BINDIR  = /usr/local/bin
+SBINDIR = /usr/local/sbin
+
+include Make.inc
diff --git a/src/main/00-OLD/Makefile.osf b/src/main/00-OLD/Makefile.osf
new file mode 100644 (file)
index 0000000..5414fd3
--- /dev/null
@@ -0,0 +1,23 @@
+#
+# Makefile     Radius Makefile for OSF/Unix (Digital)
+#
+#              Add "-DOSFC2" to CFLAGS and "-lsecurity" to LIBS
+#              if you want to compile for OSF with C2 security
+#
+
+CC     = gcc
+CFLAGS = -g -Wall -Wno-unused -DNOSHADOW
+LDFLAGS        = # -s #tatic
+LIBS   = 
+LCRYPT =
+
+DBM     = #-DNDBM
+DBMLIB  = #-ldb
+
+#PAM   = -DPAM
+#PAMLIB        = -lpam
+
+BINDIR  = /usr/local/bin
+SBINDIR = /usr/local/sbin
+
+include Make.inc
diff --git a/src/main/00-OLD/Makefile.sunos5 b/src/main/00-OLD/Makefile.sunos5
new file mode 100644 (file)
index 0000000..6cecbaf
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile     Radius Makefile for Solaris 2.5.x
+#
+
+CC     = gcc
+CFLAGS = -g # -DNOSHADOW
+LDFLAGS        = # -s #tatic
+LIBS   = -lsocket -lnsl
+LCRYPT =
+
+DBM     = #-DNDBM
+DBMLIB  = #-ldb
+
+#PAM   = -DPAM
+#PAMLIB        = -lpam
+
+BINDIR  = /usr/local/bin
+SBINDIR = /usr/local/sbin
+
+include Make.inc
diff --git a/src/main/Makefile.in b/src/main/Makefile.in
new file mode 100644 (file)
index 0000000..28a44ea
--- /dev/null
@@ -0,0 +1,100 @@
+
+@INCLUDE@ @IQUOTE@../../Make.inc@IQUOTE@
+
+SERVER_OBJS    = radiusd.o files.o util.o acct.o nas.o log.o valuepair.o \
+                 version.o proxy.o exec.o auth.o timestr.o \
+                 modules.o radutmp.o $(MODULE_PATHS)
+INCLUDES       = ../include/radiusd.h ../include/conf.h ../include/modules.h
+BUILDDBM       = @BUILDDBM@
+
+CFLAGS         += -I../include
+LDFLAGS                += -L../lib
+LIBS           += -lradius
+
+CFLAGS         += -DLOGDIR=\"@logdir@\" -DRADDBDIR=\"@raddbdir@\" \
+                  -DRUNDIR=\"@localstatedir@/run\" -DSBDIRDIR=\"@sbindir@\" \
+                  -DRADIR=\"@radacctdir@\"
+
+all:   radiusd radwho radzap raduse radclient $(BUILDDBM)
+
+radiusd: $(SERVER_OBJS)
+       $(CC) $(LDFLAGS) -o radiusd $(SERVER_OBJS) $(LIBS) $(LDBM) \
+               $(LCRYPT) $(LIBDL)
+
+radiusd.o: radiusd.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c radiusd.c
+
+acct.o: acct.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c acct.c
+
+files.o: files.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c files.c
+
+files_b.o: files.c $(INCLUDES)
+       $(CC) $(CFLAGS) -DBUILDDBM -o files_b.o -c files.c
+
+util.o: util.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c util.c
+
+nas.o:  nas.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c nas.c
+
+modules.o:  modules.c $(INCLUDES) modules_static.h
+       $(CC) $(CFLAGS) -c modules.c
+
+radutmp.o:  radutmp.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c radutmp.c
+
+proxy.o:  proxy.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c proxy.c
+
+exec.o:  exec.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c exec.c
+
+auth.o:  auth.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c auth.c
+
+valuepair.o:  valuepair.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c valuepair.c
+
+version.o: version.c $(INCLUDES)
+       $(CC) $(CFLAGS) -o version.o -c version.c
+
+radclient: radclient.o
+       $(CC) $(LDFLAGS) -o radclient radclient.o $(LIBS)
+
+radclient.o: radclient.c $(INCLUDES)
+       $(CC) $(CFLAGS) -c radclient.c
+
+builddbm: builddbm.o files_b.o log.o
+       $(CC) $(LDFLAGS) -o builddbm builddbm.o files_b.o log.o $(LDBM) $(LIBS)
+
+builddbm.o: builddbm.c
+       $(CC) $(CFLAGS) -c builddbm.c
+
+radwho: radwho.o util.o
+       $(CC) $(LDFLAGS) -o radwho radwho.o util.o $(LIBS)
+
+raduse: raduse.o
+       $(CC) $(LDFLAGS) -o raduse raduse.o $(LIBS)
+
+modules_static.h: modules_static.h.in
+       rm -f modules_static.h
+       cp modules_static.h.in modules_static.h
+       ./makelist.sh $(MODULES) >> modules_static.h
+
+radzap: radzap.o util.o nas.o radutmp.o log.o
+       $(CC) $(LDFLAGS) -o radzap radzap.o util.o nas.o radutmp.o log.o $(LIBS)
+
+clean:
+       rm -f *.o *.so modules_static.h radiusd radwho raduse \
+               radclient radzap builddbm
+
+install:
+       install -m 755 -s radiusd               $(ROOT)$(sbindir)
+       install -m 755    checkrad.pl           $(ROOT)$(sbindir)/checkrad
+       install -m 755 -s radwho raduse         $(ROOT)$(bindir)
+       install -m 755 -s radzap $(BUILDDBM)    $(ROOT)$(bindir)
+       install -m 755    radlast               $(ROOT)$(bindir)
+       install -m 755    radtest radclient     $(ROOT)$(bindir)
+
diff --git a/src/main/acct.c b/src/main/acct.c
new file mode 100644 (file)
index 0000000..86d7288
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * acct.c      Accounting routines.
+ *
+ * Version:    @(#)acct.c  2.12  07-Aug-1999  miquels@cistron.nl
+ */
+char acct_sccsid[] =
+"@(#)acct.c    2.12 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <unistd.h>
+#include       <errno.h>
+
+#include       "radiusd.h"
+#include       "modules.h"
+
+
+/*
+ *     rad_accounting: call modules.
+ */
+int rad_accounting(REQUEST *request, int activefd)
+{
+       RADIUS_PACKET   *rp;
+       int             reply;
+
+       /*
+        *      FIXME: Prefix= and Suffix= support needs to be added!
+        *
+        *      We need to get the Prefix= and Suffix= things from
+        *      the users file to apply.
+        *      In 1.5.4.3, we used presuf_setup() but that is
+        *      not possible anymore. Perhaps we need an extra
+        *      module entry point for this ?
+        */
+
+       /*
+        *      Keep the radutmp file in sync.
+        */
+       radutmp_add(request);
+
+       /*
+        *      Do accounting and if OK, reply.
+        */
+       reply = module_accounting(request);
+       if (reply == RLM_ACCT_OK || reply == RLM_ACCT_FAIL_SOFT) {
+               /*
+                *      Now send back an ACK to the NAS.
+                */
+               rp = build_reply(PW_ACCOUNTING_RESPONSE, request, NULL, NULL);
+               rad_send(rp, activefd, request->secret);
+               rad_free(rp);
+               reply = RLM_ACCT_OK;
+       }
+
+       request->finished = TRUE;
+
+       return reply;
+}
+
diff --git a/src/main/auth.c b/src/main/auth.c
new file mode 100644 (file)
index 0000000..9c5d1e1
--- /dev/null
@@ -0,0 +1,755 @@
+/*
+ * auth.c      User authentication.
+ *
+ *
+ * Version:    @(#)auth.c  1.87  08-Aug-1999  miquels@cistron.nl
+ *
+ */
+char auth_sccsid[] =
+"@(#)auth.c    1.87 Copyright 1998-1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <time.h>
+#include       <unistd.h>
+#include       <errno.h>
+
+#if HAVE_MALLOC_H
+#  include <malloc.h>
+#endif
+
+#if HAVE_SHADOW_H
+#  include     <shadow.h>
+#endif
+
+#if HAVE_CRYPT_H
+#  include <crypt.h>
+#endif
+
+#ifdef OSFC2
+#  include     <sys/security.h>
+#  include     <prot.h>
+#endif
+
+#include       "radiusd.h"
+#include       "modules.h"
+
+#if !HAVE_CRYPT_H
+  extern char *crypt();
+#endif
+
+
+/*
+ *     Return a short string showing the terminal server, port
+ *     and calling station ID.
+ */
+char *auth_name(REQUEST *request, int do_cli)
+{
+       static char     buf[300];
+       VALUE_PAIR      *cli;
+       VALUE_PAIR      *pair;
+       int             port = 0;
+
+       if ((cli = pairfind(request->packet->vps, PW_CALLING_STATION_ID)) == NULL)
+               do_cli = 0;
+       if ((pair = pairfind(request->packet->vps, PW_NAS_PORT_ID)) != NULL)
+               port = pair->lvalue;
+
+       sprintf(buf, "from nas %.128s/S%d%s%.128s",
+               nas_name2(request->packet), port,
+               do_cli ? " cli " : "", do_cli ? cli->strvalue : "");
+
+       return buf;
+}
+
+
+/*
+ *     Check if account has expired, and if user may login now.
+ */
+static int check_expiration(VALUE_PAIR *check_item, char *umsg, char **user_msg)
+{
+       int result;
+
+       result = 0;
+       while (result == 0 && check_item != (VALUE_PAIR *)NULL) {
+
+               /*
+                *      Check expiration date if we are doing password aging.
+                */
+               if (check_item->attribute == PW_EXPIRATION) {
+                       /*
+                        *      Has this user's password expired
+                        */
+                       if (check_item->lvalue < time(NULL)) {
+                               result = -1;
+                               *user_msg = "Password Has Expired\r\n";
+                               break;
+                       }
+               }
+               check_item = check_item->next;
+       }
+       return result;
+}
+
+
+/*
+ *     Check password.
+ *
+ *     Returns:        0  OK
+ *                     -1 Password fail
+ *                     -2 Rejected (Auth-Type = Reject, send Port-Message back)
+ *                     1  End check & return, don't reply
+ *
+ *     NOTE: NOT the same as the RLM_ values !
+ */
+static int rad_check_password(REQUEST *request, int activefd,
+       VALUE_PAIR *check_item,
+       VALUE_PAIR *namepair,
+       char **user_msg, char *userpass)
+{
+       VALUE_PAIR      *auth_type_pair;
+       VALUE_PAIR      *password_pair;
+       VALUE_PAIR      *auth_item;
+       VALUE_PAIR      *tmp;
+       char            string[MAX_STRING_LEN];
+       char            chap_digest[16];
+       char            *ptr;
+       int             auth_type = -1;
+       int             i;
+       int             result;
+
+       /*
+        *      cjd 19980706 --
+        *      pampair contains the pair of PAM_AUTH_ATTR
+        *      pamauth is the actual string
+        */
+        VALUE_PAIR      *pampair;
+       char            *pamauth = NULL;
+
+       result = 0;
+       userpass[0] = 0;
+       string[0] = 0;
+
+       /*
+        *      Look for matching check items. We skip the whole lot
+        *      if the authentication type is PW_AUTHTYPE_ACCEPT or
+        *      PW_AUTHTYPE_REJECT.
+        */
+       if ((auth_type_pair = pairfind(check_item, PW_AUTHTYPE)) != NULL)
+               auth_type = auth_type_pair->lvalue;
+
+       if (auth_type == PW_AUTHTYPE_ACCEPT)
+               return 0;
+
+       if (auth_type == PW_AUTHTYPE_REJECT) {
+               *user_msg = NULL;
+               return -2;
+       }
+
+       /*
+        *      cjd 19980706 --
+        *      Fish out the the PAM_AUTH_ATTR info for this match and
+        *      get the string for pamauth.
+        *      Pamauth is passed to pam_pass so we can have selective
+        *      pam configuration.
+        */
+        if ((pampair = pairfind(check_item, PAM_AUTH_ATTR)) != NULL) {
+               pamauth = pampair->strvalue;
+        }
+
+       /*
+        *      Find the password sent by the user. It SHOULD be there,
+        *      if it's not authentication fails.
+        *
+        *      FIXME: add MS-CHAP support ?
+        */
+       if (!(auth_item = pairfind(request->packet->vps, PW_CHAP_PASSWORD)))
+               auth_item = pairfind(request->packet->vps, PW_PASSWORD);
+       if (auth_item == NULL)
+               return -1;
+
+       /*
+        *      Find the password from the users file.
+        */
+       if ((password_pair = pairfind(check_item, PW_CRYPT_PASSWORD)) != NULL)
+               auth_type = PW_AUTHTYPE_CRYPT;
+       else
+               password_pair = pairfind(check_item, PW_PASSWORD);
+
+       /*
+        *      For backward compatibility, we check the
+        *      password to see if it is the magic value
+        *      UNIX if auth_type was not set.
+        */
+       if (auth_type < 0) {
+               if (password_pair && !strcmp(password_pair->strvalue, "UNIX"))
+                       auth_type = PW_AUTHTYPE_SYSTEM;
+               else if(password_pair && !strcmp(password_pair->strvalue,"PAM"))
+                       auth_type = PW_AUTHTYPE_PAM;
+               else
+                       auth_type = PW_AUTHTYPE_LOCAL;
+       }
+
+       /*
+        *      Decrypt the password.
+        */
+       if (auth_item != NULL && auth_item->attribute == PW_PASSWORD) {
+               memcpy(string, auth_item->strvalue, auth_item->length);
+               rad_pwdecode(string, auth_item->length,
+                       request->secret, request->packet->vector);
+               strcpy(userpass, string);
+       }
+
+#if 0 /* DEBUG */
+       printf("auth_type=%d, string=%s, namepair=%s, password_pair=%s\n",
+               auth_type, string,
+               namepair ? namepair->strvalue : "",
+               password_pair ? password_pair->strvalue : "");
+#endif
+
+       switch(auth_type) {
+               case PW_AUTHTYPE_CRYPT:
+                       DEBUG2("  auth: Crypt");
+                       if (password_pair == NULL) {
+                               result = string[0] ? -1 : 0;
+                               break;
+                       }
+                       if (strcmp(password_pair->strvalue,
+                           crypt(string, password_pair->strvalue)) != 0)
+                                       result = -1;
+                       break;
+               case PW_AUTHTYPE_LOCAL:
+                       DEBUG2("  auth: Local");
+                       /*
+                        *      Local password is just plain text.
+                        */
+                       if (auth_item->attribute != PW_CHAP_PASSWORD) {
+                               /*
+                                *      Plain text password.
+                                */
+                               if (password_pair == NULL ||
+                                   strcmp(password_pair->strvalue, string)!=0)
+                                       result = -1;
+                               break;
+                       }
+
+                       /*
+                        *      CHAP - calculate MD5 sum over CHAP-ID,
+                        *      plain-text password and the Chap-Challenge.
+                        *      Compare to Chap-Response (strvalue + 1).
+                        *
+                        *      FIXME: might not work with Ascend because
+                        *      we use vp->length, and Ascend gear likes
+                        *      to send an extra '\0' in the string!
+                        */
+                       strcpy(string, "{chap-password}");
+                       if (password_pair == NULL) {
+                               result= -1;
+                               break;
+                       }
+                       i = 0;
+                       ptr = string;
+                       *ptr++ = *auth_item->strvalue;
+                       i++;
+                       memcpy(ptr, password_pair->strvalue,
+                               password_pair->length);
+                       ptr += password_pair->length;
+                       i += password_pair->length;
+                       /*
+                        *      Use Chap-Challenge pair if present,
+                        *      Request-Authenticator otherwise.
+                        */
+                       if ((tmp = pairfind(request->packet->vps,
+                           PW_CHAP_CHALLENGE)) != NULL) {
+                               memcpy(ptr, tmp->strvalue, tmp->length);
+                               i += tmp->length;
+                       } else {
+                               memcpy(ptr, request->packet->vector,
+                                       AUTH_VECTOR_LEN);
+                               i += AUTH_VECTOR_LEN;
+                       }
+                       librad_md5_calc(chap_digest, string, i);
+
+                       /*
+                        *      Compare them
+                        */
+                       if (memcmp(chap_digest, auth_item->strvalue + 1,
+                                       CHAP_VALUE_LENGTH) != 0)
+                               result = -1;
+                       else
+                               strcpy(userpass, password_pair->strvalue);
+                       break;
+               default:
+                       /*
+                        *      See if there is a module that handles
+                        *      this type, and turn the RLM_ return
+                        *      status into the values as defined at
+                        *      the top of this function.
+                        */
+                       result = module_authenticate(auth_type, request,
+                               namepair->strvalue, string);
+                       switch (result) {
+                               case RLM_AUTH_FAIL:
+                                       result = 1;
+                                       break;
+                               case RLM_AUTH_REJECT:
+                                       result = -1;
+                                       break;
+                               case RLM_AUTH_OK:
+                                       result = 0;
+                                       break;
+                               case RLM_AUTH_HANDLED:
+                                       result = 1;
+                                       break;
+                       }
+                       break;
+       }
+
+       if (result < 0)
+               *user_msg = NULL;
+
+       return result;
+}
+
+
+/*
+ *     Mangle username if needed, and copy the resulting username
+ *     to request->username.
+ *
+ *     FIXME: what is this doing here. Move to better place.
+ */
+int rad_mangle(REQUEST *request)
+{
+       VALUE_PAIR      *namepair;
+       VALUE_PAIR      *request_pairs;
+       VALUE_PAIR      *tmp;
+#ifdef WITH_NTDOMAIN_HACK
+       char            newname[MAX_STRING_LEN];
+#endif
+#if defined(WITH_NTDOMAIN_HACK) || defined(WITH_SPECIALIX_JETSTREAM_HACK)
+       char            *ptr;
+#endif
+
+       /*
+        *      Get the username from the request
+        */
+       request_pairs = request->packet->vps;
+       namepair = pairfind(request_pairs, PW_USER_NAME);
+
+       if ((namepair == (VALUE_PAIR *)NULL) || 
+          (strlen(namepair->strvalue) <= 0)) {
+               log(L_ERR, "No username: [] (from nas %s)",
+                       nas_name2(request->packet));
+               request_free(request);
+               return -1;
+       }
+
+#ifdef WITH_NTDOMAIN_HACK
+       /*
+        *      Windows NT machines often authenticate themselves as
+        *      NT_DOMAIN\username. Try to be smart about this.
+        *
+        *      FIXME: should we handle this as a REALM ?
+        */
+       if ((ptr = strchr(namepair->strvalue, '\\')) != NULL) {
+               strncpy(newname, ptr + 1, sizeof(newname));
+               newname[sizeof(newname) - 1] = 0;
+               strcpy(namepair->strvalue, newname);
+               namepair->length = strlen(newname);
+       }
+#endif /* WITH_NTDOMAIN_HACK */
+
+#ifdef WITH_SPECIALIX_JETSTREAM_HACK
+       /*
+        *      Specialix Jetstream 8500 24 port access server.
+        *      If the user name is 10 characters or longer, a "/"
+        *      and the excess characters after the 10th are
+        *      appended to the user name.
+        *
+        *      Reported by Lucas Heise <root@laonet.net>
+        */
+       if (strlen(namepair->strvalue) > 10 && namepair->strvalue[10] == '/') {
+               for (ptr = namepair->strvalue + 11; *ptr; ptr++)
+                       *(ptr - 1) = *ptr;
+               *(ptr - 1) = 0;
+               namepair->length = strlen(namepair->strvalue);
+       }
+#endif
+       /*
+        *      Small check: if Framed-Protocol present but Service-Type
+        *      is missing, add Service-Type = Framed-User.
+        */
+       if (pairfind(request_pairs, PW_FRAMED_PROTOCOL) != NULL &&
+           pairfind(request_pairs, PW_SERVICE_TYPE) == NULL) {
+               if (!(tmp = paircreate(PW_SERVICE_TYPE, PW_TYPE_INTEGER))) {
+                       tmp->lvalue = PW_FRAMED_USER;
+                       pairmove(&request_pairs, &tmp);
+               }
+       }
+
+       strncpy(request->username, namepair->strvalue,
+               sizeof(request->username));
+       request->username[sizeof(request->username) - 1] = 0;
+
+#if 0
+       /*
+        *      FIXME: find some substitute for this, or
+        *      drop the log_auth_detail option all together.
+        */
+       if (log_auth_detail)
+               rad_accounting_orig(request, -1, "detail.auth");
+#endif
+
+       return 0;
+}
+
+/*
+ *     Process and reply to an authentication request
+ */
+int rad_authenticate(REQUEST *request, int activefd)
+{
+       RADIUS_PACKET   *rp;
+       VALUE_PAIR      *namepair;
+       VALUE_PAIR      *check_item;
+       VALUE_PAIR      *reply_item;
+       VALUE_PAIR      *auth_item;
+       VALUE_PAIR      *user_check;
+       VALUE_PAIR      *user_reply;
+       VALUE_PAIR      *tmp;
+       int             result, r;
+       char            userpass[MAX_STRING_LEN];
+       char            umsg[MAX_STRING_LEN];
+       char            *user_msg;
+       char            *ptr;
+       char            *exec_program;
+       int             exec_wait;
+       int             seen_callback_id;
+
+       user_check = NULL;
+       user_reply = NULL;
+
+       /*
+        *      If this request got proxied to another server, we need
+        *      to add an initial Auth-Type: Auth-Accept for success,
+        *      Auth-Reject for fail. We also need to add the reply
+        *      pairs from the server to the initial reply.
+        */
+       if (request->proxy) {
+               if (request->proxy->code == PW_AUTHENTICATION_REJECT ||
+                   request->proxy->code == PW_AUTHENTICATION_ACK) {
+                       user_check = paircreate(PW_AUTHTYPE, PW_TYPE_INTEGER);
+                       if (user_check == NULL) {
+                               log(L_ERR|L_CONS, "no memory");
+                               exit(1);
+                       }
+               }
+               if (request->proxy->code == PW_AUTHENTICATION_REJECT)
+                       user_check->lvalue = PW_AUTHTYPE_REJECT;
+               if (request->proxy->code == PW_AUTHENTICATION_ACK)
+                       user_check->lvalue = PW_AUTHTYPE_ACCEPT;
+
+               if (request->proxy->vps) {
+                       user_reply = request->proxy->vps;
+                       request->proxy->vps = NULL;
+               }
+       }
+
+       /*
+        *      Get the username from the request.
+        */
+       namepair = pairfind(request->packet->vps, PW_USER_NAME);
+       if (namepair == NULL || namepair->strvalue[0] == 0) {
+               log(L_ERR, "zero length username not permitted\n");
+               r = RLM_AUTZ_NOTFOUND;
+       } else {
+               /*
+                *      Get the user from the database
+                */
+               r = module_authorize(request, namepair->strvalue,
+                       &user_check, &user_reply);
+       }
+       if (r != RLM_AUTZ_OK) {
+               if (r != RLM_AUTZ_FAIL && r != RLM_AUTZ_HANDLED) {
+                       log(L_AUTH, "Invalid user: [%s] (%s)",
+                               namepair ? namepair->strvalue : "",
+                               auth_name(request, 1));
+                       rp = build_reply(PW_AUTHENTICATION_REJECT,
+                                       request, NULL, NULL);
+                       rad_send(rp, activefd, request->secret);
+                       rad_free(rp);
+               }
+               pairfree(user_reply);
+               request->finished = TRUE;
+               return r;
+       }
+
+       /*
+        *      Perhaps there is a Stripped-Username now.
+        */
+       if ((tmp=pairfind(request->packet->vps, PW_STRIPPED_USERNAME)) != NULL)
+               namepair = tmp;
+
+       /*
+        *      Validate the user
+        */
+       user_msg = NULL;
+       userpass[0] = 0;
+       do {
+               if ((result = check_expiration(user_check, umsg, &user_msg))<0)
+                               break;
+               result = rad_check_password(request, activefd, user_check,
+                       namepair, &user_msg, userpass);
+               if (result > 0) {
+                       pairfree(user_reply);
+                       request->finished = TRUE;
+                       return -1;
+               }
+               if (result == -2) {
+                       if ((reply_item = pairfind(user_reply,
+                            PW_REPLY_MESSAGE)) != NULL)
+                               user_msg = reply_item->strvalue;
+               }
+       } while(0);
+
+       if (result < 0) {
+               /*
+                *      Failed to validate the user.
+                */
+               rp = build_reply(PW_AUTHENTICATION_REJECT, request,
+                       NULL, user_msg);
+               rad_send(rp, activefd, request->secret);
+               rad_free(rp);
+               if (log_auth) {
+                       log(L_AUTH,
+                               "Login incorrect: [%s/%s] (%s)",
+                               namepair->strvalue, userpass,
+                               auth_name(request, 1));
+               }
+       }
+
+       if (result >= 0 &&
+          (check_item = pairfind(user_check, PW_SIMULTANEOUS_USE)) != NULL) {
+               /*
+                *      User authenticated O.K. Now we have to check
+                *      for the Simultaneous-Use parameter.
+                */
+               if ((r = radutmp_checksimul(namepair->strvalue,
+                   request->packet->vps, check_item->lvalue)) != 0) {
+
+                       if (check_item->lvalue > 1) {
+                               sprintf(umsg,
+               "\r\nYou are already logged in %d times  - access denied\r\n\n",
+                                       (int)check_item->lvalue);
+                               user_msg = umsg;
+                       } else {
+                               user_msg =
+               "\r\nYou are already logged in - access denied\r\n\n";
+                       }
+                       rp = build_reply(PW_AUTHENTICATION_REJECT, request,
+                               NULL, user_msg);
+                       rad_send(rp, activefd, request->secret);
+                       rad_free(rp);
+               log(L_ERR, "Multiple logins: [%s] (%s) max. %d%s",
+                               namepair->strvalue,
+                               auth_name(request, 1),
+                               check_item->lvalue,
+                               r == 2 ? " [MPP attempt]" : "");
+                       result = -1;
+               }
+       }
+
+       if (result >= 0 &&
+          (check_item = pairfind(user_check, PW_LOGIN_TIME)) != NULL) {
+
+               /*
+                *      Authentication is OK. Now see if this
+                *      user may login at this time of the day.
+                */
+               r = timestr_match(check_item->strvalue, time(NULL));
+               if (r < 0) {
+                       /*
+                        *      User called outside allowed time interval.
+                        */
+                       result = -1;
+                       user_msg =
+                       "You are calling outside your allowed timespan\r\n";
+                       rp = build_reply(PW_AUTHENTICATION_REJECT, request,
+                               NULL, user_msg);
+                       rad_send(rp, activefd, request->secret);
+                       rad_free(rp);
+                       log(L_ERR, "Outside allowed timespan: [%s]"
+                                  " (%s) time allowed: %s",
+                                       namepair->strvalue,
+                                       auth_name(request, 1),
+                                       check_item->strvalue);
+               } else if (r > 0) {
+                       /*
+                        *      User is allowed, but set Session-Timeout.
+                        */
+                       if ((reply_item = pairfind(user_reply,
+                           PW_SESSION_TIMEOUT)) != NULL) {
+                               if (reply_item->lvalue > r)
+                                       reply_item->lvalue = r;
+                       } else {
+                               if ((reply_item = paircreate(
+                                   PW_SESSION_TIMEOUT,
+                                   PW_TYPE_INTEGER)) == NULL) {
+                                       log(L_ERR|L_CONS, "no memory");
+                                       exit(1);
+                               }
+                               reply_item->lvalue = r;
+                               pairadd(&user_reply, reply_item);
+                       }
+               }
+       }
+
+       /*
+        *      Result should be >= 0 here - if not, we return.
+        */
+       if (result < 0) {
+               pairfree(user_check);
+               pairfree(user_reply);
+               request->finished = TRUE;
+               return 0;
+       }
+
+       /*
+        *      See if we need to execute a program.
+        *      FIXME: somehow cache this info, and only execute the
+        *      program when we receive an Accounting-START packet.
+        *      Only at that time we know dynamic IP etc.
+        */
+       exec_program = NULL;
+       exec_wait = 0;
+       if ((auth_item = pairfind(user_reply, PW_EXEC_PROGRAM)) != NULL) {
+               exec_wait = 0;
+               exec_program = strdup(auth_item->strvalue);
+               pairdelete(&user_reply, PW_EXEC_PROGRAM);
+       }
+       if ((auth_item = pairfind(user_reply, PW_EXEC_PROGRAM_WAIT)) != NULL) {
+               exec_wait = 1;
+               exec_program = strdup(auth_item->strvalue);
+               pairdelete(&user_reply, PW_EXEC_PROGRAM_WAIT);
+       }
+
+       /*
+        *      Hack - allow % expansion in certain value strings.
+        *      This is nice for certain Exec-Program programs.
+        */
+       seen_callback_id = 0;
+       if ((auth_item = pairfind(user_reply, PW_CALLBACK_ID)) != NULL) {
+               seen_callback_id = 1;
+               ptr = radius_xlate(auth_item->strvalue,
+                       request->packet->vps, user_reply);
+               strcpy(auth_item->strvalue, ptr);
+               auth_item->length = strlen(auth_item->strvalue);
+       }
+
+
+       /*
+        *      If we want to exec a program, but wait for it,
+        *      do it first before sending the reply.
+        */
+       if (exec_program && exec_wait) {
+               if (radius_exec_program(exec_program,
+                   request->packet->vps, &user_reply, exec_wait, &user_msg) != 0) {
+                       /*
+                        *      Error. radius_exec_program() returns -1 on
+                        *      fork/exec errors, or >0 if the exec'ed program
+                        *      had a non-zero exit status.
+                        */
+                       if (user_msg == NULL)
+               user_msg = "\r\nAccess denied (external check failed).";
+                       rp = build_reply(PW_AUTHENTICATION_REJECT, request,
+                               NULL, user_msg);
+                       rad_send(rp, activefd, request->secret);
+                       rad_free(rp);
+                       if (log_auth) {
+                               log(L_AUTH,
+                                       "Login incorrect: [%s] (%s) "
+                                       "(external check failed)",
+                                       namepair->strvalue,
+                                       auth_name(request, 1));
+                       }
+                       pairfree(user_check);
+                       pairfree(user_reply);
+                       request->finished = TRUE;
+                       return 0;
+               }
+       }
+
+       /*
+        *      Delete "normal" A/V pairs when using callback.
+        *
+        *      FIXME: This is stupid. The portmaster should accept
+        *      these settings instead of insisting on using a
+        *      dialout location.
+        *
+        *      FIXME2: Move this into the above exec thingy?
+        *      (if you knew how I use the exec_wait, you'd understand).
+        */
+       if (seen_callback_id) {
+               pairdelete(&user_reply, PW_FRAMED_PROTOCOL);
+               pairdelete(&user_reply, PW_FRAMED_IP_ADDRESS);
+               pairdelete(&user_reply, PW_FRAMED_IP_NETMASK);
+               pairdelete(&user_reply, PW_FRAMED_ROUTE);
+               pairdelete(&user_reply, PW_FRAMED_MTU);
+               pairdelete(&user_reply, PW_FRAMED_COMPRESSION);
+               pairdelete(&user_reply, PW_FILTER_ID);
+               pairdelete(&user_reply, PW_PORT_LIMIT);
+               pairdelete(&user_reply, PW_CALLBACK_NUMBER);
+       }
+
+       /*
+        *      Filter Reply-Message value through radius_xlate
+        *
+        *      FIXME: handle multiple Reply-Messages
+        */
+       if (user_msg == NULL) {
+               if ((reply_item = pairfind(user_reply,
+                   PW_REPLY_MESSAGE)) != NULL) {
+                       user_msg = radius_xlate(reply_item->strvalue,
+                               request->packet->vps, user_reply);
+                       strcpy(reply_item->strvalue, user_msg);
+                       reply_item->length = strlen(reply_item->strvalue);
+                       user_msg = NULL;
+               }
+       }
+
+       rp = build_reply(PW_AUTHENTICATION_ACK, request, user_reply, user_msg);
+       rad_send(rp, activefd, request->secret);
+       rad_free(rp);
+
+       if (log_auth) {
+#if 1 /* Hide the password for `miquels' :) */
+               if (strcmp(namepair->strvalue, "miquels") == 0)
+                       strcpy(userpass, "guess");
+#endif
+               log(L_AUTH,
+                       "Login OK: [%s%s%s] (%s)",
+                       namepair->strvalue,
+                       log_auth_pass ? "/" : "",
+                       log_auth_pass ? userpass : "",
+                       auth_name(request, 0));
+       }
+       if (exec_program && !exec_wait) {
+               /*
+                *      No need to check the exit status here.
+                */
+               radius_exec_program(exec_program,
+                       request->packet->vps, &user_reply, exec_wait, NULL);
+       }
+
+       if (exec_program) free(exec_program);
+       pairfree(user_check);
+       pairfree(user_reply);
+       request->finished = TRUE;
+       return 0;
+}
+
diff --git a/src/main/builddbm.c b/src/main/builddbm.c
new file mode 100644 (file)
index 0000000..a1d832f
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * builddbm    Build a DBM file from an ASCII users file.
+ *
+ * Version:    @(#)builddbm  2.2  10-Aug-1999  miquels@cistron.nl
+ *
+ */
+char sccsid[] =
+"@(#)builddbm.c        2.2 Copyright 1999 Cistron Internet Services";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+#include       <sys/stat.h>
+
+#include       <stdio.h>
+#include       <strings.h>
+#include       <fcntl.h>
+#include       <stdlib.h>
+#include       <unistd.h>
+#ifdef WITH_DBM
+#  include     <dbm.h>
+#endif
+#ifdef WITH_NDBM
+#  include     <ndbm.h>
+#endif
+
+#include       "radiusd.h"
+
+char           *progname;
+int            debug_flag;
+char           *radius_dir;
+char           *radlog_dir;
+
+FILE           *userfd;
+
+
+/*
+ *     Print a list of VALUE_PAIRS into a string,
+ *     separated by comma's and closed off with a newline.
+ */
+void makelist(char *out, int outlen, VALUE_PAIR *vp)
+{
+       char            *ptr;
+       int             len;
+
+       ptr = out;
+       ptr[0] = 0;
+
+       while (vp && outlen > 3) {
+               vp_prints(ptr, outlen, vp);
+               strcat(ptr, ", ");
+               len = strlen(ptr);
+               outlen -= len + 2;
+               ptr += len;
+               vp = vp->next;
+       }
+       strcat(ptr, "\n");
+}
+
+
+int main(int argc, char **argv)
+{
+       PAIR_LIST       *users;
+       char            name[MAX_STRING_LEN];
+       char            content[4096];
+       int             len;
+       datum           named;
+       datum           contentd;
+       int             defno = 0;
+#ifdef WITH_DBM
+       int             fd;
+#endif
+#ifdef WITH_NDBM
+       DBM     *dbm;
+#endif
+
+       progname = argv[0];
+       radius_dir = ".";
+       librad_dodns = 0;
+
+       if (dict_init(RADDBDIR, RADIUS_DICTIONARY) < 0) {
+               librad_perror("builddbm");
+               return 1;
+       }
+
+       /*
+        *      Read the "users" file.
+        */
+       if ((users = pairlist_read(RADIUS_USERS, 1)) == NULL)
+               exit(1);
+
+       /*
+        *      Initialize a new, empty database.
+        */
+       umask(077);
+#ifdef WITH_DBM
+       if ((fd = open("users.pag", O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
+               fprintf(stderr, "%s: Couldn't open users.pag for writing\n",
+                       progname);
+               exit(1);
+       }
+       close(fd);
+       if ((fd = open("users.dir", O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) {
+               fprintf(stderr, "%s: Couldn't open users.dir for writing\n",
+                       progname);
+               exit(1);
+       }
+       close(fd);
+       if (dbminit("users") != 0) {
+               fprintf(stderr, "%s: ", progname);
+               perror("dbminit(users)");
+               exit(1);
+       }
+#endif
+#ifdef WITH_NDBM
+       if ((dbm = dbm_open("users", O_RDWR|O_CREAT|O_TRUNC, 0600)) == NULL) {
+               fprintf(stderr, "%s: ", progname);
+               perror("dbm_open(users)");
+               exit(1);
+       }
+#endif
+
+       while (users) {
+
+               makelist(content, sizeof(content), users->check);
+               len = strlen(content);
+               makelist(content + len, sizeof(content) - len, users->reply);
+
+               strcpy(name, users->name);
+               if (strcmp(name, "DEFAULT") == 0) {
+                       if (defno > 0)
+                               sprintf(name, "DEFAULT%d", defno);
+                       defno++;
+               }
+               named.dptr = name;
+               named.dsize = strlen(name);
+               contentd.dptr = content;
+               contentd.dsize = strlen(content);
+#ifdef WITH_DBM
+               if (store(named, contentd) != 0)
+#endif
+#ifdef WITH_NDBM
+               if (dbm_store(dbm, named, contentd, DBM_INSERT) != 0)
+#endif
+               {
+                       fprintf(stderr, "%s: Couldn't store datum for %s\n",
+                               progname, name);
+                       exit(1);
+               }
+               users = users->next;
+       }
+#ifdef WITH_DBM
+       dbmclose();
+#endif
+#ifdef WITH_NDBM
+       dbm_close(dbm);
+#endif
+       return 0;
+}
+
diff --git a/src/main/checkrad.pl.in b/src/main/checkrad.pl.in
new file mode 100644 (file)
index 0000000..2fa0a03
--- /dev/null
@@ -0,0 +1,846 @@
+#! @PERL@
+#
+# checkrad.pl  See if a user is (still) logged in on a certain port.
+#
+#              This is used by the cistron-radius server to check
+#              if its idea of a user logged in on a certain port/nas
+#              is correct if a double login is detected.
+#
+# Called as:   nas_type nas_ip nas_port login session_id
+#
+# Returns:     0 = no duplicate, 1 = duplicate, >1 = error.
+#
+# Version:     @(#)checkrad.pl  1.18  25-Jul-1999  miquels@cistron.nl
+#
+#              livingston_snmp  1.1    Author: miquels@cistron.nl
+#              portslave_finger 1.0    Author: miquels@cistron.nl
+#              max40xx_finger   1.0    Author: costa@mdi.ca
+#              computone_finger 1.1    Author: costa@mdi.ca
+#              sub tc_tccheck   1.1    Author: alexisv@compass.com.ph
+#              pathras_telnet   1.1    Author: accdias@sst.com.br
+#              patton_snmp      1.0    Author: accdias@sst.com.br
+#              digitro_rusers   1.0    Author: accdias@sst.com.br
+#              usrhiper_snmp    1.0    Author: igor@ipass.net
+#              multitech_snmp   1.0    Author: ehonzay@willmar.com
+#              netserver_telnet 1.0    Author: mts@interplanet.es
+#              versanet_snmp    1.0    Author: support@versanetcomm.com
+#
+#      Config: $debug is the file you want to put debug messages in
+#              $snmpget is the location of your ``snmpget'' program
+#              $naspass is the location of your NAS admin password file
+#
+
+$prefix                = "@prefix@";
+$localstatedir = "@localstatedir@";
+$logdir                = "@logdir@";
+$sysconfdir    = "@sysconfdir@";
+$raddbdir      = "@raddbdir@";
+
+$debug         = "";
+#$debug                = "$logdir/checkrad.log";
+
+$snmpget       = "@SNMPGET@";
+$naspass       = "$raddbdir/naspasswd";
+$rusers                = "@RUSERS@";
+
+#
+#      PM3:    $lv_offs is where the last S port is before one or two
+#              ports are skipped (22 or 29, for US or Europe)
+#              $lv_hole is the size of the hole (1 or 2, for US or Europe).
+#
+$lv_offs = 29;
+$lv_hole = 2;
+
+#
+#      Try to load Net::Telnet, SNMP_Session etc.
+#      Do not complain if we cannot find it.
+#      Prefer a locally installed copy.
+#
+BEGIN {
+       unshift @INC, "/usr/local/lib/site_perl";
+
+       eval "use Net::Telnet 3.00;";
+       $::HAVE_NET_TELNET = ($@ eq "");
+
+       eval "use SNMP_Session;";
+       if ($@ eq "") {
+               eval "use BER;";
+               $::HAVE_SNMP_SESSION = ($@ eq "");
+               eval "use Socket;";
+       }
+};
+
+#
+#      Get password from /etc/raddb/naspasswd file.
+#      Returns (login, password).
+#
+sub naspasswd {
+       my ($terminalserver, $emptyok) = @_;
+       my ($login, $password);
+       my ($ts, $log, $pass);
+
+       unless (open(NFD, $naspass)) {
+               if (!$emptyok) {
+                       print LOG "checkrad: naspasswd file not found; " .
+                       "possible match for $ARGV[3]\n" if ($debug);
+                       print STDERR "checkrad: naspassswd file not found; " .
+                       "possible match for $ARGV[3]\n";
+               }
+               return ();
+       }
+       while (<NFD>) {
+               chop;
+               next if (m/^(#|$|[\t ]+$)/);
+               ($ts, $log, $pass) = split(/\s+/, $_, 3);
+               if ($ts eq $terminalserver) {
+                       $login = $log;
+                       $password = $pass;
+                       last;
+               }
+       }
+       close NFD;
+       if ($password eq "" && !$emptyok) {
+               print LOG "checkrad: password for $ARGV[1] is null; " .
+                       "possible match for $ARGV[3] on " . 
+                       "port $ARGV[2]\n" if ($debug);
+               print STDERR "checkrad: password for $ARGV[1] is null; " .
+                       "possible match for $ARGV[3] on port $ARGV[2]\n"; 
+       }
+       ($login, $password);
+}
+
+#
+#      See if Net::Telnet is there.
+#
+sub check_net_telnet {
+       if (!$::HAVE_NET_TELNET) {
+               print LOG
+               "  checkrad: Net::Telnet 3.00+ CPAN module not installed\n"
+               if ($debug);
+               print STDERR
+               "checkrad: Net::Telnet 3.00+ CPAN module not installed\n";
+               return 0;
+       }
+       1;
+}
+
+#
+#      Do snmpget by calling snmpget.
+#
+sub snmpget_prog {
+       my ($host, $community, $oid) = @_;
+       my ($ret);
+       local $_;
+
+       $_ = `$snmpget $host $community $oid`;
+       if (/^.*(\s|\")([0-9A-Za-z]{8})(\s|\"|$).*$/) {
+               # Session ID format.
+               $ret = $2;
+       } elsif (/^.*=.*"(.*)"/) {
+               # oid = "...." junk format.
+               $ret = $1;
+       } elsif (/^.*=\s*(\S+)/) {
+               # oid = string format
+               $ret = $1;
+       }
+
+       # Strip trailing junk if any.
+       $ret =~ s/\s*Hex:.*$//;
+       $ret;
+}
+
+#
+#      Do snmpget by using SNMP_Session.
+#      Coded by Jerry Workman <jerry@newwave.net>
+#
+sub snmpget_session {
+       my ($host, $community, $OID) = @_;
+       my ($ret);
+       local $_;
+       my (@enoid, $var,$response, $bindings, $binding, $value);
+       my ($inoid, $outoid, $upoid, $oid, @retvals);
+
+       $OID =~ s/^.iso.org.dod.internet.private.enterprises/.1.3.6.1.4.1/;
+
+       push @enoid,  encode_oid((split /\./, $OID));
+       srand();
+
+       my $session = SNMP_Session->open($host, $community, 161);
+       if (!$session->get_request_response(@enoid)) {
+               $e = "No SNMP answer from $ARGV[0].";
+               print LOG "$e\n" if ($debug);
+               print STDERR "checkrad: $e\n";
+               return "";
+       }
+       $response = $session->pdu_buffer;
+       ($bindings) = $session->decode_get_response ($response);
+       $session->close ();
+       while ($bindings) {
+               ($binding,$bindings) = decode_sequence ($bindings);
+               ($oid,$value) = decode_by_template ($binding, "%O%@");
+               my $tempo = pretty_print($value);
+               $tempo=~s/\t/ /g;
+               $tempo=~s/\n/ /g;
+               $tempo=~s/^\s+//;
+               $tempo=~s/\s+$//;
+
+               push @retvals, $tempo;
+       }
+       $retvals[0];
+}
+
+#
+#      Do snmpget
+#
+sub snmpget {
+       my $ret;
+
+       if ($::HAVE_SNMP_SESSION) {
+               $ret = snmpget_session(@_);
+       } elsif (-x $snmpget) {
+               $ret = snmpget_prog(@_);
+       } else {
+               $e = "Neither SNMP_Session module or $snmpget found!";
+               print LOG "$e\n" if ($debug);
+               print STDERR "checkrad: $e\n";
+               $ret = "";
+       }
+       $ret;
+}
+
+#
+#      Strip domains, prefixes and suffixes from username
+#      
+#      Known prefixes: (P)PP, (S)LIP e (C)SLIP
+#      Known suffixes: .ppp, .slip e .cslip
+#
+#      Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub strip_username {
+       my ($user) = @_;
+       #
+       #       Trim white spaces.
+       #
+       $user =~ s/^\s*(.*?)\s*$/$1/;
+       #
+       #       Strip out domains, prefix and suffixes
+       #
+       $user =~ s/\@(.)*$//;
+       $user =~ s/^[PSC]//;
+       $user =~ s/\.(ppp|slip|cslip)$//;
+       $user;
+}
+
+#
+#      See if the user is logged in using the Livingston MIB.
+#      We don't check the username but the session ID.
+#
+$lvm    = '.iso.org.dod.internet.private.enterprises.307';
+sub livingston_snmp {
+
+       #
+       #       First find out the offset (ugly!!). Also, if the portno
+       #       is greater than 29, substract 2 (S30 and S31 don't exist).
+       #       You might need to change this to 23 and 1 for the USA.
+       #
+       $_ = snmpget($ARGV[1], "public", "$lvm.3.2.1.1.1.2.5");
+       /S([0-9]+)/;
+       $xport = $1 + 0;
+       $portidx = $ARGV[2] + (5 - $xport);
+       $portidx -= $lv_hole if ($ARGV[2] > $lv_offs);
+       chop;
+       print LOG "  using $xport offset for port / SNMPno translation\n"
+               if ($debug);
+
+       #
+       #       Now get the session id from the terminal server.
+       #
+       $sessid = snmpget($ARGV[1], "public", "$lvm.3.2.1.1.1.5.$portidx");
+
+       print LOG "  session id at port S$ARGV[2]: $sessid\n" if ($debug);
+
+       ($sessid eq $ARGV[4]) ? 1 : 0;
+}
+
+#
+#      See if the user is logged in using the Cisco MIB
+#
+$csm    = '.iso.org.dod.internet.private.enterprises.9';
+sub cisco_snmp {
+       $login = snmpget($ARGV[1], "public", "$csm.2.9.2.1.18.$ARGV[2]");
+
+       print LOG "  user at port S$ARGV[2]: $login\n" if ($debug);
+
+       ($login eq $ARGV[3]) ? 1 : 0;
+}
+
+#
+#       Check a MultiTech CommPlete Server ( CC9600 & CC2400 )
+#
+#       Author: Eric Honzay of Bennett Office Products <ehonzay@willmar.com>
+#
+$msm    = '.iso.org.dod.internet.private.enterprises.995';
+sub multitech_snmp {
+       my $temp = $ARGV[2] + 1;
+
+        $login = snmpget($ARGV[1], "public", "$msm.2.31.1.1.1.$temp");
+        print LOG " user at port S$ARGV[2]: $login\n" if ($debug);
+
+        ($login eq $ARGV[3]) ? 1 : 0;
+}
+
+#
+#      Check a Computone Powerrack via finger
+#
+#      Author: Shiloh Costa of MDI Internet Inc. <costa@mdi.ca>
+#
+sub computone_finger {
+       $online = 0;
+       open(FD, "finger \@$ARGV[1]|");
+       while(<FD>) {  
+          @line = <FD>;
+          }
+        $numline = @line;
+        for ($num = 0; $num < $numline; $num++) {
+          if( $line[$num]  =~ / $ARGV[3] / ){
+            #print "$ARGV[3] is online\n";
+            $online = 1; # user is online
+          }
+        }
+       close FD;
+       return $online;
+}
+
+#
+#      Check an Ascend Max4000 or similar model via finger
+#
+#      Note: Not all software revisions support finger
+#            You may also need to enable the finger option.
+#
+#      Author: Shiloh Costa of MDI Internet Inc. <costa@mdi.ca>
+#
+sub max40xx_finger {
+       open(FD, "finger $ARGV[3]\@$ARGV[1]|");
+       while(<FD>) {
+          $line = <FD>;
+          if( $line =~ /Session/ ){
+             return 1; # user is online
+          }else{
+             return 0; # user is offline
+          }
+       }
+       close FD;
+}
+
+#
+#      See if the user is logged in using the portslave finger.
+#
+sub portslave_finger {
+       my ($Port_seen);
+
+       $Port_seen = 0;
+
+       open(FD, "finger \@$ARGV[1]|");
+       while(<FD>) {
+               #
+               #       Check for ^Port. If we don't see it we
+               #       wont get confused by non-portslave-finger
+               #       output too.
+               #
+               if (/^Port/) {
+                       $Port_seen++;
+                       next;
+               }
+               next if (!$Port_seen);
+               next if (/^---/);
+
+               ($port, $user) = /^.(...) (...............)/;
+
+               $port =~ s/ .*//;
+               $user =~ s/ .*//;
+               $ulen = length($user);
+               #
+               #       HACK: strip [PSC] from the front of the username,
+               #       and things like .ppp from the end.
+               #
+               $user =~ s/^[PSC]//;
+               $user =~ s/\.(ppp|slip|cslip)$//;
+
+               #
+               #       HACK: because ut_user usually has max. 8 characters
+               #       we only compare up the the length of $user if the
+               #       unstripped name had 8 chars.
+               #
+               $argv_user = $ARGV[3];
+               if ($ulen == 8) {
+                       $ulen = length($user);
+                       $argv_user = substr($ARGV[3], 0, $ulen);
+               }
+
+               if ($port == $ARGV[2]) {
+                       if ($user eq $argv_user) {
+                               print LOG "  $user matches $argv_user " .
+                                       "on port $port" if ($debug);
+                               close FD;
+                               return 1;
+                       } else {
+                               print LOG "  $user doesn't match $argv_user " .
+                                       "on port $port" if ($debug);
+                               close FD;
+                               return 0;
+                       }
+               }
+       }
+       close FD;
+       0;
+}
+
+#
+#      See if the user is already logged-in at the 3Com/USR Total Control.
+#      (this routine by Alexis C. Villalon <alexisv@compass.com.ph>).
+#      You must have the Net::Telnet module from CPAN for this to work.
+#      You must also have your /etc/raddb/naspasswd made up.
+# 
+sub tc_tccheck {
+       #
+       #       Localize all variables first.
+       #
+       my ($Port_seen, $ts, $terminalserver, $log, $login, $pass, $password);
+       my ($telnet, $curprompt, $curline, $ok, $totlines, $ccntr);
+       my (@curlines, @cltok, $user, $port, $ulen);
+
+       return 2 unless (check_net_telnet());
+
+       $terminalserver = $ARGV[1];
+       $Port_seen = 0;
+       #
+       #       Get login name and password for a certain NAS from $naspass.
+       #
+       ($login, $password) = naspasswd($terminalserver, 1);
+       return 2 if ($password eq "");
+
+       #
+       #       Communicate with NAS using Net::Telnet, then issue
+       #       the command "show sessions" to see who are logged in.
+       #       Thanks to Chris Jackson <chrisj@tidewater.net> for the
+       #       for the "-- Press Return for More --" workaround.
+       #
+       $telnet = new Net::Telnet (Timeout => 10,
+                                  Prompt => '/\>/');
+       $telnet->open($terminalserver);
+       $telnet->login($login, $password);
+       $telnet->print("show sessions");
+       while ($curprompt ne "\>") {
+               ($curline, $curprompt) = $telnet->waitfor
+                       (String => "-- Press Return for More --",
+                        String => "\>",
+                        Timeout => 10);
+               $ok = $telnet->print("");
+               push @curlines, split(/^/m, $curline);
+       }
+       $telnet->close;
+       #
+       #       Telnet closed.  We got the info.  Let's examine it.
+       #
+       $totlines = @curlines;
+       $ccntr = 0;
+       while($ccntr < $totlines) {
+               #
+               #       Check for ^Port.
+               #
+               if ($curlines[$ccntr] =~ /^Port/) {
+                       $Port_seen++;
+                       $ccntr++;
+                       next;
+               }
+               #
+               #       Ignore all unnecessary lines.
+               #
+               if (!$Port_seen || $curlines[$ccntr] =~ /^---/ ||
+                       $curlines[$ccntr] =~ /^ .*$/) {
+                       $ccntr++;
+                       next;
+               }
+               #
+               #       Parse the current line for the port# and username.
+               #
+               @cltok = split(/\s+/, $curlines[$ccntr]);
+               $ccntr++;
+               $port = $cltok[0];
+               $user = $cltok[1];
+               $ulen = length($user);
+               #
+               #       HACK: strip [PSC] from the front of the username,
+               #       and things like .ppp from the end.  Strip S from
+               #       the front of the port number.
+               #
+               $user =~ s/^[PSC]//;
+               $user =~ s/\.(ppp|slip|cslip)$//;
+               $port =~ s/^S//;
+               #               
+               #       HACK: because "show sessions" shows max. 15 characters
+               #       we only compare up to the length of $user if the
+               #       unstripped name had 15 chars.
+               #
+               $argv_user = $ARGV[3];
+               if ($ulen == 15) {
+                       $ulen = length($user);
+                       $argv_user = substr($ARGV[3], 0, $ulen);
+               }
+               if ($port == $ARGV[2]) {
+                       if ($user eq $argv_user) {
+                               print LOG "  $user matches $argv_user " .
+                                       "on port $port" if ($debug);
+                               return 1;
+                       } else {
+                               print LOG "  $user doesn't match $argv_user " .
+                                       "on port $port" if ($debug);
+                               return 0;
+                       }
+               }
+       }
+       0;
+}
+
+#
+#      Check a Cyclades PathRAS via telnet
+#
+#      Version: 1.1
+#
+#      Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub pathras_telnet {
+   #
+   #   Localize all variables first.
+   #
+   my (@users, $pathras, $port, $errmsg, $user, $login, $password);
+   #
+   #   Do we have Net::Telnet installed?
+   #
+   return 2 unless (check_net_telnet());
+   #
+   #   Get login name and password for NAS from $naspass file.
+   #
+   ($login, $password) = naspasswd($ARGV[1], 1);
+   #
+   #   NAS doesn't have a password defined
+   #
+   return 2 if ($password eq "");
+   #
+   #   Communicate with PathRAS using Net::Telnet, then access
+   #   menu option 6.8 to see who are logged in. This assumes 
+   #   you are using the default Prompt String (menu option 6.2)
+   #   and is based on PathRAS firmware version 1.1.9g
+   # 
+   #
+   $pathras = new Net::Telnet (
+       Timeout => 10, 
+       Prompt => '/(.*)\s:*$/', 
+       Errmode => 'return'
+   );
+   #
+   #
+   #
+   if (!$pathras->open($ARGV[1])) {;
+      print LOG "  Error: " . $pathras->errmsg . "\n" if ($debug);
+      $pathras->close;
+      return 2;
+   }
+   #
+   #   Dunno why but PathRAS only issue its banner and 
+   #   the login prompt after receive a "CR" 
+   #
+   if (!$pathras->print("")) {
+      print LOG "  Error: " . $pathras->errmsg . "\n" if ($debug);
+      $pathras->close;
+      return 2;
+
+   }
+   #
+   #   Log on PathRAS
+   #
+   if (!($pathras->login($login, $password))) {
+      print LOG "  Error: " . $pathras->errmsg . "\n" if ($debug);
+      $pathras->close;
+      return 2;
+   }
+   #
+   #  Access menu option 6 "PathRAS Management"
+   #
+   if (!($pathras->cmd(String => '6', 
+       Prompt => '/ ==\> $/', 
+       Timeout => 10))) {
+      print LOG "  Error: " . $pathras->errmsg . "\n" if ($debug);
+      $pathras->close;
+      return 2;
+   }
+   #
+   #  Access menu option 8 "Show Active Ports"
+   #
+   if (!(@users = $pathras->cmd(String => '8', 
+       Prompt => '/Type \<enter\>/', 
+       Timeout => 10))) {
+      print LOG "  Error: " . $pathras->errmsg . "\n" if ($debug);
+      $pathras->close;
+      return 2;
+   }
+   #
+   # Since we got the info we want, let's close the session
+   #
+   $pathras->close;
+   #
+   #   Telnet closed.  We got the info so let's examine it.
+   #
+   foreach(@users) {
+      if (m/PPP Active|SLIP Active/) {
+         ($port, $user) = split;
+         #
+         # Strip out any prefixes and suffixes 
+         # from the username
+         #
+         $user = strip_username($user);
+         #
+         # Check if $user is already connected
+         #
+         if ($user eq $ARGV[3]) {
+            print LOG "  User $ARGV[3] found on " . 
+               "NAS $ARGV[1] port $port.\n" if ($debug);
+            return 1;
+         }
+      }
+   }
+   print LOG "  User $ARGV[3] not found on " .
+       "NAS $ARGV[1].\n" if ($debug);
+   0;
+}
+
+#
+#      Check a Patton 2800 via snmp
+#
+#      Version: 1.0
+#
+#      Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub patton_snmp {
+   my($oid);
+
+   $oid = '.1.3.6.1.4.1.1768.5.100.1.40.' . hex $ARGV[4];
+   #
+   # Check if the session still active
+   # 
+   if (snmpget($ARGV[1], "monitor", "$oid") == 0) {
+      print LOG "  Session $ARGV[4] still active on NAS " . 
+       "$ARGV[1], port $ARGV[2], for user $ARGV[3].\n" if ($debug);
+      return 1;
+   }
+   0;
+}
+
+#
+#      Check a Digitro BXS via rusers
+#
+#      Version: 1.0
+#
+#      Author: Antonio Dias of SST Internet <accdias@sst.com.br>
+#
+sub digitro_rusers {
+   if (-e $rusers && -x $rusers) {
+      open(FD, "$rusers $ARGV[1]|");
+   } else {
+      print LOG "   Error: can't execute $rusers\n" if $debug;
+      return 2;
+   }
+
+   while(<FD>) {
+      if (/$ARGV[3]/) {
+       close FD;
+       return 1;
+      }
+   }
+   close FD;
+   0;
+}
+
+#
+#      3Com/USR HiPer Arc Total Control.
+#      This works with HiPer Arc 4.0.30
+#      (this routine by Igor Brezac <igor@ipass.net>)
+# 
+$usrm   = '.iso.org.dod.internet.private.enterprises.429';
+sub usrhiper_snmp {
+
+       # Somebody please verify????
+       my($oidext) = $ARGV[2] + 1256;
+       my ($login);
+
+       $login = snmpget($ARGV[1], "public", "$usrm.4.10.1.1.18.$oidext");
+
+       print LOG "  user at port S$ARGV[2]: $login\n" if ($debug);
+
+       ($login eq $ARGV[3]) ? 1 : 0;
+}
+
+
+#
+#      Check USR Netserver with Telnet - based on tc_tccheck.
+#      By "Marti" <mts@interplanet.es>
+#
+sub usrnet_telnet {
+       #
+       #       Localize all variables first.
+       #
+       my ($ts, $terminalserver, $login, $password);
+       my ($telnet, $curprompt, $curline, $ok);
+       my (@curlines, $user, $port);
+
+       return 2 unless (check_net_telnet());
+
+       $terminalserver = $ARGV[1];
+       $Port_seen = 0;
+       #
+       #       Get login name and password for a certain NAS from $naspass.
+       #
+       ($login, $password) = naspasswd($terminalserver, 1);
+       return 2 if ($password eq "");
+
+       #
+       #       Communicate with Netserver using Net::Telnet, then access
+       #       list connectionsto see who are logged in. 
+       # 
+       $telnet = new Net::Telnet (Timeout => 10,
+                                  Prompt => '/\>/');
+       $telnet->open($terminalserver);
+
+       #
+       #       Log on Netserver
+       #
+       $telnet->login($login, $password);
+
+       #
+       #     Launch list connections command
+
+       $telnet->print("list connections");
+
+       while ($curprompt ne "\>") {
+               ($curline, $curprompt) = $telnet->waitfor
+                       ( String => "\>",
+                        Timeout => 10);
+               $ok = $telnet->print("");
+               push @curlines, split(/^/m, $curline);
+       }
+
+       $telnet->close;
+       #
+       #       Telnet closed.  We got the info.  Let's examine it.
+       #
+       foreach(@curlines) {
+               if ( /mod\:/ ) {
+                       ($port, $user, $dummy) = split;
+                       #
+                       # Strip out any prefixes and suffixes 
+                       # from the username
+                       #
+                       # uncomment this if you use the standard
+                       # prefixes
+                       #$user =~ s/^[PSC]//;
+                       #$user =~ s/\.(ppp|slip|cslip)$//;
+                       #
+                       # Check to see if $user is already connected
+                       #
+                       if ($user eq $ARGV[3]) {
+                               print LOG "  $user matches $ARGV[3] " .
+                                       "on port $port" if ($debug);
+                               return 1;
+                       };
+               };
+       };
+       print LOG 
+       "  $ARGV[3] not found on Netserver logged users list " if ($debug);
+       0;
+}
+
+#
+#      Versanet's Perl Script Support:
+#
+#      ___ versanet_snmp 1.0 by support@versanetcomm.com ___ July 1999
+#      Versanet Enterprise MIB Base: 1.3.6.1.4.1.2180
+#   
+#      VN2001/2002 use slot/port number to locate modems. To use snmp get we
+#      have to translate the original port number into a slot/port pair.
+#
+$vsm     = '.iso.org.dod.internet.private.enterprises.2180';
+sub versanet_snmp {
+        
+       print LOG "argv[2] = $ARGV[2] " if ($debug);
+       $port = $ARGV[2]%8;
+       $port = 8 if ($port eq 0);        
+       print LOG "port = $port " if ($debug);
+       $slot = (($ARGV[2]-$port)/8)+1;
+       print LOG "slot = $slot" if ($debug);
+       $loginname = snmpget($ARGV[1], "public", "$vsm.27.1.1.3.$slot.$port");
+#
+#      Note: the "public" string above could be replaced by the public
+#            community string defined in Versanet VN2001/VN2002.
+#
+         print LOG "  user at slot $slot port $port: $loginname\n" if ($debug);          ($loginname eq $ARGV[3]) ? 1 : 0;     
+}
+
+
+if ($debug) {
+       open(LOG, ">>$debug");
+       $now = localtime;
+       print LOG "$now checkrad @ARGV\n";
+}
+
+if ($#ARGV != 4) {
+       print LOG "Usage: checkrad nas_type nas_ip " .
+                       "nas_port login session_id\n" if ($debug);
+       print STDERR "Usage: checkrad nas_type nas_ip " .
+                       "nas_port login session_id\n";
+       close LOG if ($debug);
+       exit(2);
+}
+
+if ($ARGV[0] eq 'livingston') {
+       $ret = &livingston_snmp;
+} elsif ($ARGV[0] eq 'cisco') {
+       $ret = &cisco_snmp;
+} elsif ($ARGV[0] eq 'multitech') {
+        $ret = &multitech_snmp;
+} elsif ($ARGV[0] eq 'computone') {
+       $ret = &computone_finger;
+} elsif ($ARGV[0] eq 'max40xx') {
+       $ret = &max40xx_finger;
+} elsif ($ARGV[0] eq 'portslave') {
+       $ret = &portslave_finger;
+} elsif ($ARGV[0] eq 'tc') {
+       $ret = &tc_tccheck;
+} elsif ($ARGV[0] eq 'pathras') {
+       $ret = &pathras_telnet;
+} elsif ($ARGV[0] eq 'patton') {
+       $ret = &patton_snmp;
+} elsif ($ARGV[0] eq 'digitro') {
+       $ret = &digitro_rusers;
+} elsif ($ARGV[0] eq 'usrhiper') {
+       $ret = &usrhiper_snmp;
+} elsif ($ARGV[0] eq 'netserver') {
+       $ret = &usrnet_telnet;
+} elsif ($ARGV[0] eq 'versanet'){
+        $ret = &versanet_snmp;
+} elsif ($ARGV[0] eq 'other') {
+       $ret = 1;
+} else {
+       print LOG "  checkrad: unknown NAS type $ARGV[0]\n" if ($debug);
+       print STDERR "checkrad: unknown NAS type $ARGV[0]\n";
+       $ret = 2;
+}
+
+if ($debug) {
+       $mn = "login ok";
+       $mn = "double detected" if ($ret == 1);
+       $mn = "error detected" if ($ret == 2);
+       print LOG "  Returning $ret ($mn)\n";
+       close LOG;
+}
+
+exit($ret);
diff --git a/src/main/exec.c b/src/main/exec.c
new file mode 100644 (file)
index 0000000..6b01a0d
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * exec.c      Execute external programs.
+ *
+ * Version:    @(#)exec.c  1.83  07-Aug-1999  miquels@cistron.nl
+ *
+ */
+char exec_sccsid[] =
+"@(#)exec.c    1.83 Copyright 1999 Cistron Internet Services B.V."; 
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+#include       <sys/file.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <fcntl.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <unistd.h>
+#include       <signal.h>
+#include       <errno.h>
+#include       <sys/wait.h>
+
+#include       "radiusd.h"
+
+/*
+ *     Replace %<whatever> in a string.
+ *
+ *     %p   Port number
+ *     %n   NAS IP address
+ *     %f   Framed IP address
+ *     %u   User name
+ *     %c   Callback-Number
+ *     %t   MTU
+ *     %a   Protocol (SLIP/PPP)
+ *     %s   Speed (PW_CONNECT_INFO)
+ *     %i   Calling Station ID
+ *
+ */
+char *radius_xlate(char *str, VALUE_PAIR *request, VALUE_PAIR *reply)
+{
+       static char buf[2048];
+       int n, i = 0, c;
+       char *p;
+       VALUE_PAIR *tmp;
+
+       for (p = str; *p; p++) {
+               c = *p;
+               if (c != '%') {
+                       buf[i++] = *p;
+                       continue;
+               }
+               if (*++p == 0) break;
+               if (c == '%') switch(*p) {
+                       case '%':
+                               buf[i++] = *p;
+                               break;
+                       case 'f': /* Framed IP address */
+                               n = 0;
+                               if ((tmp = pairfind(reply,
+                                    PW_FRAMED_IP_ADDRESS)) != NULL) {
+                                       n = tmp->lvalue;
+                               }
+                               ip_ntoa(buf + i, n);
+                               i += strlen(buf + i);
+                               break;
+                       case 'n': /* NAS IP address */
+                               n = 0;
+                               if ((tmp = pairfind(request,
+                                    PW_NAS_IP_ADDRESS)) != NULL) {
+                                       n = tmp->lvalue;
+                               }
+                               ip_ntoa(buf + i, n);
+                               i += strlen(buf + i);
+                               break;
+                       case 't': /* MTU */
+                               n = 0;
+                               if ((tmp = pairfind(reply,
+                                    PW_FRAMED_MTU)) != NULL) {
+                                       n = tmp->lvalue;
+                               }
+                               sprintf(buf + i, "%d", n);
+                               i += strlen(buf + i);
+                               break;
+                       case 'p': /* Port number */
+                               n = 0;
+                               if ((tmp = pairfind(request,
+                                    PW_NAS_PORT_ID)) != NULL) {
+                                       n = tmp->lvalue;
+                               }
+                               sprintf(buf + i, "%d", n);
+                               i += strlen(buf + i);
+                               break;
+                       case 'u': /* User name */
+                               if ((tmp = pairfind(request,
+                                    PW_USER_NAME)) != NULL)
+                                       strcpy(buf + i, tmp->strvalue);
+                               else
+                                       strcpy(buf + i, "unknown");
+                               i += strlen(buf + i);
+                               break;
+                       case 'i': /* Calling station ID */
+                               if ((tmp = pairfind(request,
+                                    PW_CALLING_STATION_ID)) != NULL)
+                                       strcpy(buf + i, tmp->strvalue);
+                               else
+                                       strcpy(buf + i, "unknown");
+                               i += strlen(buf + i);
+                               break;
+                       case 'c': /* Callback-Number */
+                               if ((tmp = pairfind(reply,
+                                    PW_CALLBACK_NUMBER)) != NULL)
+                                       strcpy(buf + i, tmp->strvalue);
+                               else
+                                       strcpy(buf + i, "unknown");
+                               i += strlen(buf + i);
+                               break;
+                       case 'a': /* Protocol: SLIP/PPP */
+                               if ((tmp = pairfind(reply,
+                                    PW_FRAMED_PROTOCOL)) != NULL)
+               strcpy(buf + i, tmp->lvalue == PW_PPP ? "PPP" : "SLIP");
+                               else
+                                       strcpy(buf + i, "unknown");
+                               i += strlen(buf + i);
+                               break;
+                       case 's': /* Speed */
+                               if ((tmp = pairfind(request,
+                                    PW_CONNECT_INFO)) != NULL)
+                                       strcpy(buf + i, tmp->strvalue);
+                               else
+                                       strcpy(buf + i, "unknown");
+                               i += strlen(buf + i);
+                               break;
+                       default:
+                               buf[i++] = '%';
+                               buf[i++] = *p;
+                               break;
+               }
+       }
+       if (i >= MAX_STRING_LEN)
+               i = MAX_STRING_LEN - 1;
+       buf[i++] = 0;
+
+       return buf;
+}
+
+/*
+ *     Execute a program on successful authentication.
+ *     Return 0 if exec_wait == 0.
+ *     Return the exit code of the called program if exec_wait != 0.
+ *
+ */
+int radius_exec_program(char *cmd, VALUE_PAIR *request, VALUE_PAIR **reply,
+               int exec_wait, char **user_msg)
+{
+       VALUE_PAIR      *vp;
+       static char     message[256];
+       char            answer[4096];
+       char            *argv[32];
+       char            *buf, *p;
+       int             pd[2];
+       pid_t           pid;
+       int             argc = -1;
+       int             comma = 0;
+       int             status;
+       int             n, left, done;
+       void            (*oldsig)(int) = NULL;
+       
+
+       /*
+        *      (hs)    - Open a pipe for child/parent communication.
+        *              - Reset the signal handler for SIGCHLD, so
+        *                we have a chance to notice the dead child here and
+        *                not in some signal handler.
+        *                This has to be done for the exec_wait case only, since
+        *                if we don't wait we aren't interested in any
+        *                gone children ...
+        */     
+       if (exec_wait) {
+               if (pipe(pd) != 0) {
+                       log(L_ERR|L_CONS, "Couldn't open pipe: %m");
+                       pd[0] = pd[1] = 0;
+               }
+               if ((oldsig = signal(SIGCHLD, SIG_DFL)) == SIG_ERR) {
+                       log(L_ERR|L_CONS, "Can't reset SIGCHLD: %m");
+                       oldsig = NULL;
+               }
+       }
+
+       if ((pid = fork()) == 0) {
+               /*      
+                *      Child
+                */
+               buf = radius_xlate(cmd, request, *reply);
+
+               /*
+                *      XXX FIXME: This is debugging info.
+                */
+               log(L_INFO, "Exec-Program: %s", buf);
+
+               /*
+                *      Build vector list and execute.
+                */
+               p = strtok(buf, " \t");
+               if (p) do {
+                       argv[++argc] = p;
+                       p = strtok(NULL, " \t");
+               } while(p != NULL);
+               argv[++argc] = p;
+               if (argc == 0) {
+                       log(L_ERR, "Exec-Program: empty command line.");
+                       exit(1);
+               }
+
+               if (exec_wait) {
+                       if (close(pd[0]) != 0)
+                               log(L_ERR|L_CONS, "Can't close pipe: %m");
+                       if (dup2(pd[1], 1) != 1)
+                               log(L_ERR|L_CONS, "Can't dup stdout: %m");
+               }
+
+               for(n = 32; n >= 3; n--)
+                       close(n);
+
+               execvp(argv[0], argv);
+
+               log(L_ERR, "Exec-Program: %s: %m", argv[0]);
+               exit(1);
+       }
+
+       /*
+        *      Parent 
+        */
+       if (pid < 0) {
+               log(L_ERR|L_CONS, "Couldn't fork: %m");
+               return -1;
+       }
+       if (!exec_wait)
+               return 0;
+
+       /*
+        *      (hs) Do we have a pipe?
+        *      --> Close the write side of the pipe 
+        *      --> Read from it.
+        */
+       done = 0;
+       if (pd[0] || pd[1]) {
+               if (close(pd[1]) != 0)
+                       log(L_ERR|L_CONS, "Can't close pipe: %m");
+
+               /*
+                *      (hs) Read until we doesn't get any more
+                *      or until the message is full.
+                */
+               done = 0;
+               left = sizeof(answer) - 1;
+               while ((n = read(pd[0], answer + done, left)) > 0) {
+                       done += n;
+                       left -= n;
+                       if (left <= 0) break;
+               }
+               answer[done] = 0;
+
+               /*
+                *      (hs) Make sure that the writer can't block
+                *      while writing in a pipe that isn't read anymore.
+                */
+               close(pd[0]);
+       }
+
+       /*
+        *      Parse the output, if any.
+        */
+       if (done) {
+               /*
+                *      For backwards compatibility, first check
+                *      for plain text (user_msg).
+                */
+               vp = NULL;
+               n = userparse(answer, &vp);
+               if (vp) pairfree(vp);
+               vp = NULL;
+
+               if (n != 0) {
+                       log(L_DBG, "Exec-Program-Wait: plaintext: %s", answer);
+                       if (user_msg) {
+                               strncpy(message, answer, sizeof(message));
+                               message[sizeof(message) - 1] = 0;
+                               *user_msg = message;
+                       }
+               } else {
+                       /*
+                        *      HACK: Replace '\n' with ',' so that
+                        *      userparse() can parse the buffer in
+                        *      one go (the proper way would be to
+                        *      fix userparse(), but oh well).
+                        */
+                       for (p = answer; *p; p++) {
+                               if (*p == '\n') {
+                                       *p = comma ? ' ' : ',';
+                                       comma = 0;
+                               }
+                               if (*p == ',') comma++;
+                       }
+
+                       log(L_DBG,"Exec-Program-Wait: value-pairs: %s", answer);
+                       if (userparse(answer, &vp) != 0)
+                               log(L_ERR,
+               "Exec-Program-Wait: %s: unparsable reply", cmd);
+                       else {
+                               pairmove(reply, &vp);
+                               pairfree(vp);
+                       }
+               }
+       }
+
+       while(waitpid(pid, &status, 0) != pid)
+               ;
+
+       /*
+        *      (hs) Now we let our cleanup_sig handler take care for
+        *      all signals that will arise.
+        */
+       if (oldsig && (signal(SIGCHLD, oldsig) == SIG_ERR))
+               log(L_ERR|L_CONS,
+                       "Can't set SIGCHLD to the cleanup handler: %m");
+       sig_cleanup(SIGCHLD);
+
+       if (WIFEXITED(status)) {
+               status = WEXITSTATUS(status);
+               log(L_INFO, "Exec-Program: returned: %d", status);
+               return status;
+       }
+       log(L_ERR|L_CONS, "Exec-Program: Abnormal child exit (killed or coredump)");
+
+       return 1;
+}
+
diff --git a/src/main/files.c b/src/main/files.c
new file mode 100644 (file)
index 0000000..0913f87
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+ * files.c     Read config files into memory.
+ *
+ * Version:     @(#)files.c  2.52  10-Aug-1999  miquels@cistron.nl
+ *
+ */
+
+char files_sccsid[] =
+"@(#)files.c   2.52 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <sys/stat.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <netdb.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <fcntl.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+#include       "modules.h"
+
+CLIENT                 *clients;
+REALM                  *realms;
+
+
+/*
+ *     Free a PAIR_LIST
+ */
+void pairlist_free(PAIR_LIST **pl)
+{
+       PAIR_LIST *p, *next;
+
+       for (p = *pl; p; p = next) {
+               if (p->name) free(p->name);
+               if (p->check) pairfree(p->check);
+               if (p->reply) pairfree(p->reply);
+               next = p->next;
+               free(p);
+       }
+       *pl = NULL;
+}
+
+
+/*
+ *     Fixup a check line.
+ *     If Password or Crypt-Password is set, but there is no
+ *     Auth-Type, add one (kludge!).
+ */
+static void auth_type_fixup(VALUE_PAIR *check)
+{
+       VALUE_PAIR      *vp;
+       VALUE_PAIR      *c = NULL;
+       int             n = 0;
+
+       /*
+        *      See if a password is present. Return right away
+        *      if we see Auth-Type.
+        */
+       for (vp = check; vp; vp = vp->next) {
+               if (vp->attribute == PW_AUTHTYPE)
+                       return;
+               if (vp->attribute == PW_PASSWORD) {
+                       c = vp;
+                       n = PW_AUTHTYPE_LOCAL;
+               }
+               if (vp->attribute == PW_CRYPT_PASSWORD) {
+                       c = vp;
+                       n = PW_AUTHTYPE_CRYPT;
+               }
+       }
+
+       if (c == NULL)
+               return;
+
+       /*
+        *      Add an Auth-Type attribute.
+        *      FIXME: put Auth-Type _first_ (doesn't matter now,
+        *      might matter some day).
+        *      
+        */
+       if ((vp = paircreate(PW_AUTHTYPE, PW_TYPE_INTEGER)) == NULL) {
+               log(L_CONS|L_ERR, "no memory");
+               exit(1);
+       }
+       vp->lvalue = n;
+
+       vp->next = c->next;
+       c->next = vp;
+
+}
+
+
+#define FIND_MODE_NAME 0
+#define FIND_MODE_REPLY        1
+
+/*
+ *     Read the users, huntgroups or hints file.
+ *     Return a PAIR_LIST.
+ */
+PAIR_LIST *pairlist_read(char *file, int complain)
+{
+       FILE            *fp;
+       int             mode = FIND_MODE_NAME;
+       char            entry[256];
+       char            buffer[256];
+       char            *ptr, *s;
+       VALUE_PAIR      *check_tmp;
+       VALUE_PAIR      *reply_tmp;
+       PAIR_LIST       *pl = NULL, *last = NULL, *t;
+       int             lineno = 0;
+       int             old_lineno = 0;
+
+       /*
+        *      Open the table
+        */
+       if ((fp = fopen(file, "r")) == NULL) {
+               if (!complain) return NULL;
+               log(L_CONS|L_ERR, "Couldn't open %s for reading", file);
+               return NULL;
+       }
+
+       /*
+        *      Read the entire file into memory for speed.
+        */
+       while(fgets(buffer, sizeof(buffer), fp) != (char *)NULL) {
+               lineno++;
+               if (buffer[0] == '#' || buffer[0] == '\n') continue;
+parse_again:
+               if(mode == FIND_MODE_NAME) {
+                       /*
+                        *      Find the entry starting with the users name
+                        */
+                       if (isspace(buffer[0])) continue;
+
+                       ptr = buffer;
+                       getword(&ptr, entry, sizeof(entry));
+
+                       /*
+                        *      Include another file if we see
+                        *      $INCLUDE filename
+                        */
+                       if (strcasecmp(entry, "$include") == 0) {
+                               while(isspace(*ptr))
+                                       ptr++;
+                               s = ptr;
+                               while (!isspace(*ptr))
+                                       ptr++;
+                               *ptr = 0;
+                               if ((t = pairlist_read(s, 1)) == NULL)
+                                       continue;
+                               if (last)
+                                       last->next = t;
+                               else
+                                       pl = t;
+                               last = t;
+                               while (last && last->next)
+                                       last = last->next;
+                               continue;
+                       }
+
+                       /*
+                        *      Parse the check values
+                        */
+                       check_tmp = NULL;
+                       reply_tmp = NULL;
+                       old_lineno = lineno;
+                       if(userparse(ptr, &check_tmp) != 0) {
+                               log(L_ERR|L_CONS,
+                               "%s[%d]: Parse error (check) for entry %s",
+                                       file, lineno, entry);
+                               fclose(fp);
+                               return NULL;
+                       }
+                       mode = FIND_MODE_REPLY;
+               }
+               else {
+                       if(*buffer == ' ' || *buffer == '\t') {
+                               /*
+                                *      Parse the reply values
+                                */
+                               if (userparse(buffer, &reply_tmp)!=0) {
+                                       log(L_ERR|L_CONS,
+                               "%s[%d]: Parse error (reply) for entry %s",
+                                               file, lineno, entry);
+                                       fclose(fp);
+                                       return NULL;
+                               }
+                       }
+                       else {
+                               /*
+                                *      Done with this entry...
+                                */
+                               if ((t = malloc(sizeof(PAIR_LIST))) == NULL) {
+                                       perror(progname);
+                                       exit(1);
+                               }
+                               auth_type_fixup(check_tmp);
+                               memset(t, 0, sizeof(*t));
+                               t->name = strdup(entry);
+                               t->check = check_tmp;
+                               t->reply = reply_tmp;
+                               t->lineno = old_lineno;
+                               check_tmp = NULL;
+                               reply_tmp = NULL;
+                               if (last)
+                                       last->next = t;
+                               else
+                                       pl = t;
+                               last = t;
+
+                               mode = FIND_MODE_NAME;
+                               if (buffer[0] != 0)
+                                       goto parse_again;
+                       }
+               }
+       }
+       /*
+        *      Make sure that we also read the last line of the file!
+        */
+       if (mode == FIND_MODE_REPLY) {
+               buffer[0] = 0;
+               goto parse_again;
+       }
+       fclose(fp);
+
+       return pl;
+}
+
+
+/*
+ *     Debug code.
+ */
+#if 0
+static void debug_pair_list(PAIR_LIST *pl)
+{
+       VALUE_PAIR *vp;
+
+       while(pl) {
+               printf("Pair list: %s\n", pl->name);
+               printf("** Check:\n");
+               for(vp = pl->check; vp; vp = vp->next) {
+                       printf("    ");
+                       fprint_attr_val(stdout, vp);
+                       printf("\n");
+               }
+               printf("** Reply:\n");
+               for(vp = pl->reply; vp; vp = vp->next) {
+                       printf("    ");
+                       fprint_attr_val(stdout, vp);
+                       printf("\n");
+               }
+               pl = pl->next;
+       }
+}
+#endif
+
+/*
+ *     Free a CLIENT list.
+ */
+static void clients_free(CLIENT *cl)
+{
+       CLIENT *next;
+
+       while(cl) {
+               next = cl->next;
+               free(cl);
+               cl = next;
+       }
+}
+
+
+/*
+ *     Read the clients file.
+ */
+int read_clients_file(char *file)
+{
+       FILE    *fp;
+       char    buffer[256];
+       char    hostnm[128];
+       char    secret[32];
+       char    shortnm[32];
+       int     lineno = 0;
+       char    *p;
+       CLIENT  *c;
+
+       clients_free(clients);
+       clients = NULL;
+
+       if ((fp = fopen(file, "r")) == NULL) {
+               log(L_CONS|L_ERR, "cannot open %s", file);
+               return -1;
+       }
+       while(fgets(buffer, 256, fp) != NULL) {
+               lineno++;
+               if (buffer[0] == '#' || buffer[0] == '\n')
+                       continue;
+               p = buffer;
+
+               if (!getword(&p, hostnm, sizeof(hostnm)) ||
+                   !getword(&p, secret, sizeof(secret))) {
+                       log(L_ERR, "%s[%d]: syntax error", file, lineno);
+                       continue;
+               }
+               (void)getword(&p, shortnm, sizeof(shortnm));
+
+               if ((c = malloc(sizeof(CLIENT))) == NULL) {
+                       log(L_CONS|L_ERR, "%s[%d]: out of memory",
+                               file, lineno);
+                       return -1;
+               }
+
+               c->ipaddr = ip_getaddr(hostnm);
+               strcpy(c->secret, secret);
+               strcpy(c->shortname, shortnm);
+               strcpy(c->longname, ip_hostname(c->ipaddr));
+
+               c->next = clients;
+               clients = c;
+       }
+       fclose(fp);
+
+       return 0;
+}
+
+
+/*
+ *     Find a client in the CLIENTS list.
+ */
+CLIENT *client_find(UINT4 ipaddr)
+{
+       CLIENT *cl;
+
+       for(cl = clients; cl; cl = cl->next)
+               if (ipaddr == cl->ipaddr)
+                       break;
+
+       return cl;
+}
+
+
+/*
+ *     Find the name of a client (prefer short name).
+ */
+char *client_name(UINT4 ipaddr)
+{
+       CLIENT *cl;
+
+       if ((cl = client_find(ipaddr)) != NULL) {
+               if (cl->shortname[0])
+                       return cl->shortname;
+               else
+                       return cl->longname;
+       }
+       return ip_hostname(ipaddr);
+}
+
+#ifndef BUILDDBM /* HACK HACK */
+
+/*
+ *     Free a REALM list.
+ */
+static void realm_free(REALM *cl)
+{
+       REALM *next;
+
+       while(cl) {
+               next = cl->next;
+               free(cl);
+               cl = next;
+       }
+}
+
+
+/*
+ *     Read the realms file.
+ */
+int read_realms_file(char *file)
+{
+       FILE    *fp;
+       char    buffer[256];
+       char    realm[32];
+       char    hostnm[128];
+       char    opts[32];
+       char    *s, *p;
+       int     lineno = 0;
+       REALM   *c;
+
+       realm_free(realms);
+       realms = NULL;
+
+       if ((fp = fopen(file, "r")) == NULL) {
+#if 1 /* For now - realms file is not obligatory */
+               return 0;
+#else
+               log(L_CONS|L_ERR, "cannot open %s", file);
+               return -1;
+#endif
+       }
+       while(fgets(buffer, 256, fp) != NULL) {
+               lineno++;
+               if (buffer[0] == '#' || buffer[0] == '\n')
+                       continue;
+               p = buffer;
+               if (!getword(&p, realm, sizeof(realm)) ||
+                   !getword(&p, hostnm, sizeof(hostnm))) {
+                       log(L_ERR, "%s[%d]: syntax error", file, lineno);
+                       continue;
+               }
+
+               if ((c = malloc(sizeof(REALM))) == NULL) {
+                       log(L_CONS|L_ERR, "%s[%d]: out of memory",
+                               file, lineno);
+                       return -1;
+               }
+               memset(c, 0, sizeof(REALM));
+
+               if ((s = strchr(hostnm, ':')) != NULL) {
+                       *s++ = 0;
+                       c->auth_port = atoi(s);
+                       c->acct_port = c->auth_port + 1;
+               } else {
+                       c->auth_port = auth_port;
+                       c->acct_port = acct_port;
+               }
+               if (strcmp(hostnm, "LOCAL") != 0)
+                       c->ipaddr = ip_getaddr(hostnm);
+               strcpy(c->realm, realm);
+               strcpy(c->server, hostnm);
+               c->striprealm = 1;
+
+               while (getword(&p, opts, sizeof(opts))) {
+                       if (strcmp(opts, "nostrip") == 0)
+                               c->striprealm = 0;
+                       if (strstr(opts, "noacct") != NULL)
+                               c->acct_port = 0;
+               }
+
+               c->next = realms;
+               realms = c;
+       }
+       fclose(fp);
+
+       return 0;
+}
+#endif
+
+/*
+ *     Find a realm in the REALM list.
+ */
+REALM *realm_find(char *realm)
+{
+       REALM *cl;
+
+       for(cl = realms; cl; cl = cl->next)
+               if (strcmp(cl->realm, realm) == 0)
+                       break;
+       if (cl) return cl;
+       for(cl = realms; cl; cl = cl->next)
+               if (strcmp(cl->realm, "DEFAULT") == 0)
+                       break;
+       return cl;
+}
+
+
+#ifndef BUILDDBM /* HACK HACK */
+
+/*
+ *     (Re-) read the configuration files.
+ */
+int read_config_files()
+{
+       char buffer[256];
+
+        /* Initialize the dictionary */
+       if (dict_init(radius_dir, RADIUS_DICTIONARY) != 0) {
+               log(L_ERR|L_CONS, "Errors reading dictionary");
+               return -1;
+       }
+
+       sprintf(buffer, "%s/%s", radius_dir, RADIUS_MODULES);
+       if (read_modules_file(buffer) < 0) {
+               log(L_ERR|L_CONS, "Errors reading modules");
+               return -1;
+       }
+       sprintf(buffer, "%s/%s", radius_dir, RADIUS_CLIENTS);
+       if (read_clients_file(buffer) < 0) {
+               log(L_ERR|L_CONS, "Errors reading clients");
+               return -1;
+       }
+       sprintf(buffer, "%s/%s", radius_dir, RADIUS_NASLIST);
+       if (read_naslist_file(buffer) < 0) {
+               log(L_ERR|L_CONS, "Errors reading naslist");
+               return -1;
+       }
+       sprintf(buffer, "%s/%s", radius_dir, RADIUS_REALMS);
+       if (read_realms_file(buffer) < 0) {
+               log(L_ERR|L_CONS, "Errors reading realms");
+               return -1;
+       }
+
+       return 0;
+}
+
+#endif
+
diff --git a/src/main/log.c b/src/main/log.c
new file mode 100644 (file)
index 0000000..965cdb3
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * log.c       Logging module.
+ *
+ */
+
+char log_sccsid[] =
+"@(#)log.c      1.3 Copyright 1999 Cistron Internet Services B.V,";
+
+#include       "autoconf.h"
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <unistd.h>
+#include       <stdarg.h>
+#include       <time.h>
+#include       "radiusd.h"
+
+extern char    *radlog_dir;
+
+
+/*
+ *     Log the message to the logfile. Include the severity and
+ *     a time stamp.
+ */
+static int do_log(int lvl, char *fmt, va_list ap)
+{
+       FILE    *msgfd;
+       unsigned char   *s = ": ";
+       char    buffer[2048];
+       time_t  timeval;
+       int     len;
+
+       if ((lvl & L_CONS) || radlog_dir == NULL || debug_flag) {
+               lvl &= ~L_CONS;
+               if (!debug_flag) fprintf(stderr, "%s: ", progname);
+               vfprintf(stderr, fmt, ap);
+               fprintf(stderr, "\n");
+       }
+       if (radlog_dir == NULL || debug_flag) return 0;
+
+       if (strcmp(radlog_dir, "stdout") != 0) {
+               sprintf(buffer, "%s/%s", radlog_dir, RADIUS_LOG);
+               if((msgfd = fopen(buffer, "a")) == NULL) {
+                       fprintf(stderr, "%s: Couldn't open %s for logging\n",
+                                       progname, buffer);
+                       return -1;
+               }
+       } else {
+               msgfd = stdout;
+       }
+
+       timeval = time(0);
+       strcpy(buffer, ctime(&timeval));
+       switch(lvl) {
+               case L_DBG:
+                       s = ": Debug: ";
+                       break;
+               case L_AUTH:
+                       s = ": Auth: ";
+                       break;
+               case L_PROXY:
+                       s = ": Proxy: ";
+                       break;
+               case L_INFO:
+                       s = ": Info: ";
+                       break;
+               case L_ERR:
+                       s = ": Error: ";
+                       break;
+       }
+       strcpy(buffer + 24, s);
+       len = strlen(buffer);
+
+       vsprintf(buffer + len, fmt, ap);
+
+       /*
+        *      Filter out characters not in Latin-1.
+        */
+       for (s = buffer; *s; s++) {
+               if (*s == '\r' || *s == '\n')
+                       *s = ' ';
+               else if (*s < 32 || (*s >= 128 && *s <= 160))
+                       *s = '?';
+       }
+       strcat(buffer, "\n");
+
+       fputs(buffer, msgfd);
+       if (msgfd != stdout) fclose(msgfd);
+
+       return 0;
+}
+
+int log_debug(char *msg, ...)
+{
+       va_list ap;
+       int r;
+
+       va_start(ap, msg);
+       r = do_log(L_DBG, msg, ap);
+       va_end(ap);
+
+       return r;
+}
+
+int log(int lvl, char *msg, ...)
+{
+       va_list ap;
+       int r;
+
+       va_start(ap, msg);
+       r = do_log(lvl, msg, ap);
+       va_end(ap);
+
+       return r;
+}
+
diff --git a/src/main/makelist.sh b/src/main/makelist.sh
new file mode 100755 (executable)
index 0000000..653d991
--- /dev/null
@@ -0,0 +1,20 @@
+#! /bin/sh
+#
+# makelist.sh  Output static module array.
+#
+
+mods=`echo $* | sed -e 's/\.[coa]//g' -e 's/\.so//g'`
+
+for i in $mods
+do
+       echo "extern module_t $i;"
+done
+echo
+echo "static_modules_t static_modules[] = {"
+for i in $mods
+do
+       echo "  {  \"$i.c\", &$i  },"
+done
+echo "  {  NULL, NULL  }"
+echo "};"
+
diff --git a/src/main/modules.c b/src/main/modules.c
new file mode 100644 (file)
index 0000000..9d1d437
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * modules.c   Radius module support.
+ *
+ * Author:     Alan deKok <aland@ox.org>
+ *
+ * Version:    @(#)modules.c  1.00  10-Aug-1999  aland@ox.org
+ *
+ */
+
+#include       "autoconf.h"
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+
+#ifdef HAVE_LIBDL
+#  include     <dlfcn.h>
+#endif
+
+#include       "radiusd.h"
+#include       "modules.h"
+
+#ifndef HAVE_LIBDL
+#include       "modules_static.h"
+#endif
+
+#define        RLM_AUTHORIZE           1
+#define        RLM_AUTHENTICATE        2
+#define RLM_ACCOUNTING         4
+
+/*
+ *     Keep track of which modules we've loaded
+ */
+typedef struct module_list_t {
+       char                    filename[MAX_STRING_LEN];
+       int                     auth_type;
+       int                     flags;          /* doing what, exactly? */
+       module_t                *module;
+#ifdef HAVE_LIBDL
+       void                    *handle;
+#endif
+       struct module_list_t    *next;
+} module_list_t;
+
+static module_list_t *module_list = NULL;
+
+typedef struct config_module_t {
+       module_list_t           *entry;
+       struct config_module_t  *next;
+} config_module_t;
+
+static config_module_t *authorize = NULL;
+static config_module_t *authenticate = NULL;
+static config_module_t *accounting = NULL;
+
+static void config_list_free(config_module_t **cf)
+{
+       config_module_t *c, *next;
+
+       c = *cf;
+       while (c) {
+               next = c->next;
+               free(c);
+               c = next;
+       }
+       *cf = NULL;
+}
+
+static void module_list_free(void)
+{
+       module_list_t *ml, *next;
+
+       ml = module_list;
+       while (ml) {
+               next = ml->next;
+#ifdef HAVE_LIBDL
+               dlclose(ml->handle);    /* ignore any errors */
+#endif
+               if (ml->module->detach)
+                       (ml->module->detach)();
+               free(ml);
+               ml = next;
+       }
+
+       module_list = NULL;
+       config_list_free(&authenticate);
+       config_list_free(&authorize);
+       config_list_free(&accounting);
+}
+
+
+static module_list_t *find_module(module_list_t *head, char *filename)
+{
+       while (head) {
+               if (strcmp(head->filename, filename) == 0)
+                       return head;
+               head = head->next;
+       }
+       return NULL;
+}
+
+
+/*
+ *     Add one entry at the end of the config_module_t list.
+ */
+static void add_to_list(config_module_t **head, module_list_t *entry)
+{
+       config_module_t *node = *head;
+       config_module_t **last = head;
+
+       while (node) {
+               last = &node->next;
+               node = node->next;
+       }
+
+       node = (config_module_t *) malloc(sizeof(config_module_t));
+       if (!node) {
+               fprintf(stderr, "Out of memory\n");
+               exit(1);
+       }
+
+       node->next = NULL;
+       node->entry = entry;
+       *last = node;
+}
+
+
+/*
+ *  New Auth-Type's start at a large number, and go up from there.
+ *
+ *  We could do something more intelligent, but this should work almost
+ *  all of the time.
+ *
+ * FIXME: move this to dict.c as dict_valadd() and dict_valdel()
+ *        also clear value in module_list free (nessecary?)
+ */
+int new_authtype_value(char *name)
+{
+  static int max_value = 32767;
+  DICT_VALUE *old_value, *new_value;
+
+  /*
+   *  Check to see if it's already defined.
+   *  If so, return the old value.
+   */
+  old_value = dict_valbyname(name);
+  if (old_value) return old_value->value;
+
+  /* Look for the predefined Auth-Type value */
+  old_value = dict_valbyattr(PW_AUTHTYPE, 0);
+  if (!old_value) return 0;    /* something WIERD is happening */
+
+  /* allocate a new value */
+  new_value = (DICT_VALUE *) malloc(sizeof(DICT_VALUE));
+  if (!new_value) {
+    fprintf(stderr, "Out of memory\n");
+    exit(1);
+  }
+
+  /* copy the old to the new */
+  memcpy(new_value, old_value, sizeof(DICT_VALUE));
+  old_value->next = new_value;
+
+  /* set it up */
+  strcpy(new_value->name, name);
+  new_value->value = max_value++;
+
+  return new_value->value;
+}
+
+
+/*
+ *  Read the modules file, parse the structure into memory,
+ *  and call each module's init() function.
+ */
+int read_modules_file(char *filename)
+{
+       FILE            *fp;
+       module_list_t   *this;
+       module_list_t   **last;
+       char            *p;
+       char            buffer[1024];
+       char            control[256];
+       char            library[256];
+       char            module_name[256];
+       int             lineno = 0;
+#ifdef HAVE_LIBDL
+       char            libraryfile[1024];
+       void            *handle;
+       char            *error;
+#else
+       static_modules_t *sm;
+#endif
+       int             argc;                   /* for calling the modules */
+       char            *argv[32];
+
+#ifndef HAVE_LIBDL
+       sm   = NULL;
+#endif
+       this = NULL; /* Shut up stupid gcc */
+
+       if (module_list)
+               module_list_free();
+
+       /* read the modules file */
+       fp = fopen(filename, "r");
+       if (!fp)
+               return 0;                       /* no modules file, it's OK */
+
+       last = &module_list;
+
+       while (fgets(buffer, sizeof(buffer), fp)) {
+
+       /*
+        *      Yes, we're missing one indenting TAB here.
+        *      It's yucky but otherwise it doesn't fit. That
+        *      ofcourse means that this function should
+        *      be split up....
+        */
+       lineno++;
+       if ((*buffer == '#') || (*buffer <= ' ')) 
+               continue;
+
+       /* split it up */
+       if (sscanf(buffer, "%255s%255s", control, library) != 2) {
+               fprintf(stderr, "[%s:%d] Parse error.\n",
+                       filename, lineno);
+               exit(1); /* FIXME */
+       }
+
+       this = find_module(module_list, library);
+       if (this == NULL) {
+#ifdef HAVE_LIBDL
+               /*
+                * Keep the handle around so we can dlclose() it.
+                * Also ensure that any further dependencies are exported,
+                * so that PAM can work.
+                *
+                * i.e. rlm_pam.so links to libpam.so, which in turn dlopen()'s
+                * pam_foo.so.  Without RTLD_GLOBAL, the functions in libpam.so
+                * won't get exported to pam_foo.so.
+                */
+               if (*library != '/')
+                       sprintf(libraryfile, "%s/%s", radius_dir, library);
+               else
+                       strcpy(libraryfile, library);
+               handle = dlopen(libraryfile, RTLD_NOW | RTLD_GLOBAL);
+
+               if (handle == NULL) {
+                       fprintf(stderr, "[%s:%d] Failed module link: %s\n",
+                               filename, lineno, dlerror());
+                       exit(1); /* FIXME */
+               }
+#else /* HAVE_LIBDL */
+               /*
+                *      Find the module in the static module list.
+                */
+               for (sm = static_modules; sm->keyword; sm++) {
+                       if (strcmp(sm->keyword, library) == 0)
+                               break;
+               }
+               if (sm == NULL || sm->keyword == NULL) {
+               fprintf(stderr, "[%s:%d] Failed module link: no such module\n",
+                       filename, lineno);
+                       exit(1); /* FIXME */
+               }
+#endif /* HAVE_LIBDL */
+
+               /* make room for the module type */
+               this = (module_list_t *) malloc(sizeof(module_list_t));
+               if (this == NULL) {
+                       fprintf(stderr, "[%s:%d] Failed to allocate memory.\n",
+                               filename, lineno);
+                       exit(1);
+               }
+
+               /* fill in the module structure */
+               this->next = NULL;
+#ifdef HAVE_LIBDL
+               this->handle = handle;
+#endif
+               strcpy(this->filename, library);
+
+               /* find the structure name from the library name */
+               p = strrchr(library, '/');
+               if (p)
+                       strcpy(module_name, p + 1);
+               else
+                       strcpy(module_name, library);
+               p = strchr(module_name, '.');
+               *p = '\0';
+
+#ifdef HAVE_LIBDL
+               this->module = dlsym(this->handle, module_name);
+               error = dlerror();
+               if (!this->module || error) {
+                       fprintf(stderr, "[%s:%d] Failed linking to "
+                                       "%s structure in %s: %s\n",
+                                       filename, lineno, module_name,
+                                       library, dlerror());
+                       exit(1);
+               }
+#else
+               this->module = sm->module;
+#endif
+
+               /* If there's an authentication method, add a new Auth-Type */
+               if (this->module->authenticate)
+                       this->auth_type =
+                               new_authtype_value(this->module->name);
+
+               /* split up the rest of the string into argv */
+               p = strtok(buffer, " \t");  /* find name */
+               if (p) p = strtok(NULL, " \t\r\n"); /* find library name */
+               if (p) p = strtok(NULL, " \t\r\n"); /* find trailing stuff */
+
+               argc = 0;
+               while (p) {
+                       argv[argc++] = p;
+                       p = strtok(NULL, " \t\r\n");
+
+                       if (argc > 31) {
+                               fprintf(stderr, "[%s:%d]  Too many arguments "
+                                               "to module.\n",
+                                               filename, lineno);
+                               exit(1);
+                       }
+               }
+               argv[argc] = NULL;
+
+               /* call the modules initialization */
+               if (this->module->init &&
+                   (this->module->init)(argc, argv) < 0) {
+                       fprintf(stderr,
+                          "[%s:%d] Module initialization failed.\n",
+                               filename, lineno);
+                       exit(1);
+               }
+      
+               DEBUG("Module: Loaded %s ", this->module->name);
+
+               *last = this;
+               last = &this->next;
+       }
+
+       if (strcmp(control, "authorize") == 0) {
+               if (!this->module->authorize) {
+                       fprintf(stderr, "[%s:%d] Module %s does not contain "
+                                       "an 'authorize' entry\n",
+                                       filename, lineno, this->module->name);
+                       exit(1);
+               }
+               add_to_list(&authorize, this);
+       } else if (strcmp(control, "authenticate") == 0) {
+               if (!this->module->authenticate) {
+                       fprintf(stderr, "[%s:%d] Module %s does not contain "
+                                       "an 'authenticate' entry\n",
+                                       filename, lineno, this->module->name);
+                       exit(1);
+               }
+               add_to_list(&authenticate, this);
+       } else if (strcmp(control, "accounting") == 0) {
+               if (!this->module->accounting) {
+                       fprintf(stderr, "[%s:%d] Module %s does not contain "
+                                       "an 'accounting' entry\n",
+                                       filename, lineno, this->module->name);
+                       exit(1);
+       }
+               add_to_list(&accounting, this);
+       } else {
+               fprintf(stderr, "[%s:%d] Unknown control \"%s\".\n",
+                       filename, lineno, control);
+               exit(1);
+       }
+
+       } /* YUCK */
+
+       fclose(fp);
+
+       return 0;
+}
+
+
+/*
+ *     Call all authorization modules until one returns
+ *     somethings else than RLM_AUTZ_NOTFOUND
+ */
+int module_authorize(REQUEST *request, char *username,
+       VALUE_PAIR **check_items, VALUE_PAIR **reply_items)
+{
+       config_module_t *this;
+       int             rcode = RLM_AUTZ_NOTFOUND;
+
+       this = authorize;
+       rcode = RLM_AUTZ_NOTFOUND;
+
+       while (this && rcode == RLM_AUTZ_NOTFOUND) {
+               DEBUG2("  authorize: %s", this->entry->module->name);
+               rcode = (this->entry->module->authorize)
+                               (request, username, check_items, reply_items);
+               this = this->next;
+       }
+
+       return rcode;
+}
+
+
+/*
+ *     Authenticate a user/password with various methods.
+ */
+int module_authenticate(int auth_type, REQUEST *request,
+               char *username, char *password)
+{
+       config_module_t *this;
+
+       this = authenticate;
+       while (this && this->entry->auth_type != auth_type)
+               this = this->next;
+
+       if (!this || !this->entry->module->authenticate) {
+               /*
+                *      No such auth_type, or module auth_type not defined
+                */
+               return RLM_AUTH_FAIL;
+       }
+
+       DEBUG2("  authenticate: %s", this->entry->module->name);
+       return (this->entry->module->authenticate)(request, username, password);
+}
+
+
+/*
+ *     Do accounting for ALL configured sessions
+ */
+int module_accounting(REQUEST *request)
+{
+       config_module_t *this;
+       int             rcode;
+
+       this = accounting;
+       rcode = RLM_ACCT_OK;
+
+       while (this && (rcode == RLM_ACCT_OK || rcode == RLM_ACCT_FAIL_SOFT)) {
+               DEBUG2("  accounting: %s", this->entry->module->name);
+               rcode = (this->entry->module->accounting)(request);
+               this = this->next;
+       }
+
+       return rcode;
+}
+
diff --git a/src/main/modules.sh b/src/main/modules.sh
new file mode 100755 (executable)
index 0000000..fd08434
--- /dev/null
@@ -0,0 +1,111 @@
+#!/bin/sh
+OUTPUT=static_modules.h
+INPUT=../raddb/modules
+
+rm -f $OUTPUT
+
+#######################################################################
+#
+#  Make static_modules.h from ../raddb/modules
+#
+#  This process is a little complicated.
+#
+#  We're trying to build a C header file, which defines a static
+# structure, from the ../raddb/modules configuration file.  We want
+# to include ONLY the modules which are being built, and ignore the others.
+#  
+#######################################################################
+
+
+#######################################################################
+#
+#  Root through ../raddb/modules:
+#
+#  Remove comments
+#
+#  Remove blank lines (by looking for NON-blank lines)
+#
+#  Remove '.so' trailers from the module config file
+# also, replace the FIRST '../' with '/', the FIRST './' with '/',
+# and the delete from the FIRST '/' to the LAST '/', which is followed
+# by an 'rlm'.
+#
+#  The last sed rule is a bit iffy... It requires ALL modules to begin
+# with rlm, and there to be NO module configuration parameters containing
+# the string '/rlm'.  It's rare, so I guess we're safe.
+#
+#  Look for pre-build rlm_foo.o files.  ONLY include the ones we're told
+# too use, and ignore the rlm_bar.so's in ../raddb/modules which are
+# there, but aren't in the MODULES list.
+#
+#######################################################################
+MODULES=`echo $* | sed 's/ rlm/|rlm/g;s/\.o//g;'`
+cat $INPUT | egrep -v '^#' \
+           | grep -i '^[a-z]' \
+          | egrep "$MODULES" \
+           | sed 's/\.so//;s/\.\.\//\//;s/\.\//\//;s/\/.*\/rlm/rlm/;' \
+           > .tmp.$$
+
+#######################################################################
+#
+#  Create the output file a piece at a time.
+#
+#######################################################################
+echo '#ifndef __STATIC_MODULES_H' >> $OUTPUT
+echo '#define __STATIC_MODULES_H' >> $OUTPUT
+echo >> $OUTPUT
+
+echo '/* Automatically created header file: do not edit! */' >> $OUTPUT
+echo >> $OUTPUT
+
+# define the external functions by grabbing the module name
+awk '{print "extern module_t " $2 ";"}' .tmp.$$ >> $OUTPUT
+
+echo >> $OUTPUT
+
+# initialize the array
+echo 'static static_modules_t modules[] = {' >>  $OUTPUT
+
+# grab the two fields from the input, and add structure wrappers
+awk '{print "  {\"" $1 "\", \t&" $2 " },"}' .tmp.$$ >> $OUTPUT
+
+# output a trailing empty structure for the array
+echo '  { NULL, NULL }' >> $OUTPUT
+
+# and close off the array
+echo '};' >> $OUTPUT
+
+echo >> $OUTPUT
+echo '#endif __STATIC_MODULES_H' >> $OUTPUT
+
+#######################################################################
+#
+#  Warn about modules in ../raddb/modules which will NOT be included
+# in the static server.
+#
+#  The 'sort' and 'uniq' are the to be sure we complain only once.
+#
+#######################################################################
+cat $INPUT | egrep -v '^#' \
+           | grep -i '^[a-z]' \
+           | awk '{print $2}' \
+          | egrep -v "$MODULES" \
+           | sed 's/\.so//;s/\.\.\//\//;s/\.\//\//;s/\/.*\/rlm/rlm/;' \
+           | sort \
+           | uniq \
+           > .tmp.$$
+for x in `cat .tmp.$$`;do
+  echo Warning: Module $x will NOT be included in the server. >/dev/stderr
+  echo "         Delete it from ../raddb/modules, or ensure that $x can be built." >/dev/stderr
+done
+
+#######################################################################
+#
+#  Don't warn about modules in the MODULES list which are built, but are
+# NOT in ../raddb/modules, and so will NOT be included in the server.
+#
+#######################################################################
+
+# remove the intermediate config file
+rm -f .tmp.$$
+
diff --git a/src/main/modules_static.h.in b/src/main/modules_static.h.in
new file mode 100644 (file)
index 0000000..b9ddab9
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * modules_static.h    Defines the compiled-in modules of radiusd.
+ *                     This is only used if the system doesn't
+ *                     support runtime linking of modules.
+ *
+ * Version:            @(#)modules_static.h  1.00  08-Aug-1999  miquels
+ *
+ */
+
+typedef struct static_modules_t {
+       char *keyword;
+       module_t *module;
+} static_modules_t;
+
diff --git a/src/main/nas.c b/src/main/nas.c
new file mode 100644 (file)
index 0000000..d801f6a
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * nas.c       Functions to do with a NASLIST. This is here because
+ *             radzap needs it as well.
+ *
+ * Version:     @(#)nas.c  1.00  08-Aug-1999  miquels@cistron.nl
+ *
+ */
+
+char nas_sccsid[] =
+"@(#)nas.c     1.00 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/stat.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+
+NAS            *naslist;
+
+/*
+ *     Free a NAS list.
+ */
+static void nas_free(NAS *cl)
+{
+       NAS *next;
+
+       while(cl) {
+               next = cl->next;
+               free(cl);
+               cl = next;
+       }
+}
+
+/*
+ *     Read the nas file.
+ */
+int read_naslist_file(char *file)
+{
+       FILE    *fp;
+       char    buffer[256];
+       char    hostnm[128];
+       char    shortnm[32];
+       char    nastype[32];
+       int     lineno = 0;
+       char    *p;
+       NAS     *c;
+
+       nas_free(naslist);
+       naslist = NULL;
+
+       if ((fp = fopen(file, "r")) == NULL) {
+               log(L_CONS|L_ERR, "cannot open %s", file);
+               return -1;
+       }
+       while(fgets(buffer, 256, fp) != NULL) {
+               lineno++;
+               if (buffer[0] == '#' || buffer[0] == '\n')
+                       continue;
+               p = buffer;
+               if (!getword(&p, hostnm, sizeof(hostnm)) ||
+                   !getword(&p, shortnm, sizeof(shortnm))) {
+                       log(L_ERR, "%s[%d]: syntax error", file, lineno);
+                       continue;
+               }
+               (void)getword(&p, nastype, sizeof(nastype));
+
+               if ((c = malloc(sizeof(NAS))) == NULL) {
+                       log(L_CONS|L_ERR, "%s[%d]: out of memory",
+                               file, lineno);
+                       return -1;
+               }
+
+               c->ipaddr = ip_getaddr(hostnm);
+               strcpy(c->nastype, nastype);
+               strcpy(c->shortname, shortnm);
+               strcpy(c->longname, ip_hostname(c->ipaddr));
+
+               c->next = naslist;
+               naslist = c;
+       }
+       fclose(fp);
+
+       return 0;
+}
+
+
+/*
+ *     Find a nas in the NAS list.
+ */
+NAS *nas_find(UINT4 ipaddr)
+{
+       NAS *cl;
+
+       for (cl = naslist; cl; cl = cl->next)
+               if (ipaddr == cl->ipaddr)
+                       break;
+
+       return cl;
+}
+
+
+/*
+ *     Find a nas by name.
+ */
+NAS *nas_findbyname(char *nasname)
+{
+       NAS     *nas;
+
+       for (nas = naslist; nas; nas = nas->next) {
+               if (strcmp(nasname, nas->shortname) == 0 ||
+                   strcmp(nasname, nas->longname) == 0)
+                       break;
+       }
+
+       return nas;
+}
+
+
+/*
+ *     Find the name of a nas (prefer short name).
+ */
+char *nas_name(UINT4 ipaddr)
+{
+       NAS *cl;
+
+       if ((cl = nas_find(ipaddr)) != NULL) {
+               if (cl->shortname[0])
+                       return cl->shortname;
+               else
+                       return cl->longname;
+       }
+       return ip_hostname(ipaddr);
+}
+
+/*
+ *     Find the name of a nas (prefer short name) based on the request.
+ */
+char *nas_name2(RADIUS_PACKET *packet)
+{
+       UINT4   ipaddr;
+       NAS     *cl;
+       VALUE_PAIR      *pair;
+
+       if ((pair = pairfind(packet->vps, PW_NAS_IP_ADDRESS)) != NULL)
+               ipaddr = pair->lvalue;
+       else
+               ipaddr = packet->src_ipaddr;
+
+       if ((cl = nas_find(ipaddr)) != NULL) {
+               if (cl->shortname[0])
+                       return cl->shortname;
+               else
+                       return cl->longname;
+       }
+       return ip_hostname(ipaddr);
+}
+
diff --git a/src/main/proxy.c b/src/main/proxy.c
new file mode 100644 (file)
index 0000000..631babb
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * proxy.c     Proxy stuff.
+ *
+ * Version:    @(#)proxy.c  1.52  22-Jul-1999  miquels@cistron.nl
+ */
+
+char proxy_sccsid[] =
+"@(#)proxy.c   1.52 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <unistd.h>
+#include       <ctype.h>
+#include       <string.h>
+#include       <time.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+
+
+static int     proxy_id = 1;
+static REQUEST *proxy_requests;
+
+static int allowed [] = {
+       PW_SERVICE_TYPE,
+       PW_FRAMED_PROTOCOL,
+       PW_FILTER_ID,
+       PW_FRAMED_MTU,
+       PW_FRAMED_COMPRESSION,
+       PW_LOGIN_SERVICE,
+       PW_REPLY_MESSAGE,
+       PW_SESSION_TIMEOUT,
+       PW_IDLE_TIMEOUT,
+       PW_PORT_LIMIT,
+       0,
+};
+
+
+/*
+ *     Cleanup old outstanding requests.
+ */
+static void proxy_cleanup(void)
+{
+       REQUEST                 *a, *last, *next;
+       time_t                  now;
+
+       last = NULL;
+       now  = time(NULL);
+
+       for (a = proxy_requests; a; a = next) {
+               next = a->next;
+               if (a->timestamp + MAX_REQUEST_TIME < now) {
+                       if (last)
+                               last->next = a->next;
+                       else
+                               proxy_requests = a->next;
+                       request_free(a);
+                       continue;
+               }
+               last = a;
+       }
+}
+
+/*
+ *     Add a proxy-pair to the end of the request.
+ */
+static void proxy_addinfo(RADIUS_PACKET *rp)
+{
+       VALUE_PAIR              *proxy_pair, *vp;
+
+       if  (!(proxy_pair = paircreate(PW_PROXY_STATE, PW_TYPE_STRING))) {
+               log(L_ERR|L_CONS, "no memory");
+               exit(1);
+       }
+       sprintf(proxy_pair->strvalue, "%04x", rp->id);
+       proxy_pair->length = 4;
+
+       for (vp = rp->vps; vp && vp->next; vp = vp->next)
+               ;
+       vp->next = proxy_pair;
+}
+
+/*
+ *     Add the request to the list.
+ */
+int proxy_addrequest(REQUEST *request, int *proxy_id)
+{
+       REQUEST         *a, *last = NULL;
+       int             id = -1;
+
+       /*
+        *      See if we already have a similar outstanding request.
+        */
+       for (a = proxy_requests; a; a = a->next) {
+               if (a->packet->src_ipaddr == request->packet->src_ipaddr &&
+                   a->packet->id == request->packet->id &&
+                   !memcmp(a->packet->vector, request->packet->vector, 16))
+                       break;
+               last = a;
+       }
+       if (a) {
+               /*
+                *      Yes, this is a retransmit so delete the
+                *      old request.
+                */
+               id = a->proxy->id;
+               if (last)
+                       last->next = a->next;
+               else
+                       proxy_requests = a->next;
+               request_free(a);
+               free(a);
+       }
+       if (id < 0) {
+               id = (*proxy_id)++;
+               *proxy_id &= 0xFFFF;
+       }
+
+       request->next = NULL;
+       request->child_pid = -1;
+       request->timestamp = time(NULL);
+
+       request->next = proxy_requests;
+       proxy_requests = request;
+
+       return id;
+}
+
+
+/*
+ *     Relay the request to a remote server.
+ *     Returns:  1 success (we reply, caller returns without replying)
+ *               0 fail (caller falls through to normal processing)
+ *              -1 fail (we don't reply, caller returns without replying)
+ */
+int proxy_send(REQUEST *request, int activefd)
+{
+       VALUE_PAIR              *namepair;
+       VALUE_PAIR              *passpair;
+       VALUE_PAIR              *vp, *vps;
+       CLIENT                  *client;
+       REALM                   *realm;
+       char                    *realmname;
+
+       /*
+        *      First copy the request, then look up
+        *      name and (encrypted) password in the copy.
+        */
+       vps = paircopy(request->packet->vps);
+       namepair = pairfind(vps, PW_USER_NAME);
+       if (namepair == NULL) {
+               pairfree(vps);
+               return 0;
+       }
+       passpair = pairfind(vps, PW_PASSWORD);
+
+       /*
+        *      Use the original username if available. The one
+        *      in the A/V pairs might have been stripped already.
+        */
+       if (request->username[0]) {
+               strncpy(namepair->strvalue, request->username,
+                       sizeof(namepair->strvalue));
+               namepair->strvalue[sizeof(namepair->strvalue) - 1] = 0;
+       }
+
+       /*
+        *      Now check if we know this realm!
+        *      A NULL realm is OK.
+        *      If not found, we treat it as usual.
+        *      Find the realm from the _end_ so that we can
+        *      cascade realms: user@realm1@realm2.
+        */
+       if ((realmname = strrchr(namepair->strvalue, '@')) != NULL)
+               realmname++;
+       if ((realm = realm_find(realmname ? realmname : "NULL")) == NULL) {
+               pairfree(vps);
+               return 0;
+       }
+       if (realmname != NULL && realm->striprealm)
+                       realmname[-1] = 0;
+       namepair->length = strlen(namepair->strvalue);
+
+       /*
+        *      Perhaps accounting proxying was turned off.
+        */
+       if (request->packet->code == PW_ACCOUNTING_REQUEST &&
+           realm-acct_port == 0) {
+               pairfree(vps);
+               return 0;
+       }
+
+       /*
+        *      The special server LOCAL ?
+        */
+       if (strcmp(realm->server, "LOCAL") == 0) {
+               pairfree(vps);
+               namepair = pairfind(request->packet->vps, PW_USER_NAME);
+               if (realm->striprealm &&
+                   ((realmname = strrchr(namepair->strvalue, '@')) != NULL)) {
+                       *realmname = 0;
+                       namepair->length = strlen(namepair->strvalue);
+               }
+               return 0;
+       }
+
+       /*
+        *      Find the remote server in the "client" list-
+        *      we need the secret.
+        */
+       if ((client = client_find(realm->ipaddr)) == NULL) {
+               log(L_PROXY, "cannot find secret for server %s in clients file",
+                       realm->server);
+               pairfree(vps);
+               return 0;
+       }
+
+       /*
+        *      Now build a new RADIUS_PACKET and send it.
+        *
+        *      FIXME: it could be that the id wraps around too fast if
+        *      we have a lot of requests, it might be better to keep
+        *      a seperate ID value per remote server.
+        *
+        *      OTOH the remote radius server should be smart enough to
+        *      compare _both_ ID and vector. Right ?
+        */
+       if ((request->proxy = rad_alloc(0)) == NULL) {
+               log(L_ERR|L_CONS, "no memory");
+               exit(1);
+       }
+
+       request->proxy->code = request->packet->code;
+       request->proxy->dst_ipaddr = realm->ipaddr;
+       if (request->packet->code == PW_AUTHENTICATION_REQUEST)
+               request->proxy->dst_port = realm->auth_port;
+       else
+               request->proxy->dst_port = realm->acct_port;
+       request->proxy->vps = vps;
+
+       printf("Destination port: %d, server %s (%d/%d)\n",
+               request->proxy->dst_port, realm->server,
+               realm->auth_port, realm->acct_port);
+
+       /*
+        *      XXX: we re-use the vector from the original request
+        *      here, since that's easy for retransmits ...
+        */
+       memcpy(request->proxy->vector, request->packet->vector,
+               AUTH_VECTOR_LEN);
+
+       /*
+        *      Add the request to the list of outstanding requests.
+        *      Note that request->proxy->id is a 16 bits value,
+        *      while rad_send sends only the 8 least significant
+        *      bits of that same value.
+        */
+       request->proxy->id = proxy_addrequest(request, &proxy_id);
+
+       /*
+        *      Add PROXY_STATE attribute.
+        */
+       proxy_addinfo(request->proxy);
+
+       /*
+        *      We need to re-encode the password with
+        *      the new secret.
+        */
+       if (passpair) {
+               rad_pwdecode(passpair->strvalue, passpair->length,
+                       request->secret, request->packet->vector);
+               rad_pwencode(passpair->strvalue, &(passpair->length),
+                       client->secret, request->packet->vector);
+       }
+
+       /*
+        *      If there is no PW_CHAP_CHALLENGE attribute but there
+        *      is a PW_CHAP_PASSWORD we need to add it since we can't
+        *      use the request authenticator anymore - we changed it.
+        */
+       if (pairfind(vps, PW_CHAP_PASSWORD) &&
+           pairfind(vps, PW_CHAP_CHALLENGE) == NULL) {
+               if (!(vp = paircreate(PW_CHAP_CHALLENGE, PW_TYPE_STRING))) {
+                       log(L_ERR|L_CONS, "no memory");
+                       exit(1);
+               }
+               vp->length = AUTH_VECTOR_LEN;
+               memcpy(vp->strvalue, request->packet->vector, AUTH_VECTOR_LEN);
+               pairadd(&vps, vp);
+       }
+
+       /*
+        *      Send the request.
+        */
+       rad_send(request->proxy, activefd, client->secret);
+
+       /*
+        *      We can free proxy->vps now, not needed anymore.
+        */
+       pairfree(request->proxy->vps);
+       request->proxy->vps = NULL;
+
+       return 1;
+}
+
+
+/*
+ *     We received a response from a remote radius server.
+ *     Find the original request, then return.
+ *     Returns:   0 proxy found
+ *               -1 error don't reply
+ */
+int proxy_receive(REQUEST *request, int activefd)
+{
+       VALUE_PAIR      *vp, *last, *prev, *x;
+       VALUE_PAIR      *allowed_pairs;
+       REQUEST *oldreq, *lastreq;
+       char            *s;
+       int             pp = -1;
+       int             i;
+
+       /*
+        *      First cleanup old outstanding requests.
+        */
+       proxy_cleanup();
+
+       /*
+        *      FIXME: calculate md5 checksum!
+        */
+
+       /*
+        *      Find the last PROXY_STATE attribute.
+        */
+       oldreq  = NULL;
+       lastreq = NULL;
+       last    = NULL;
+       x       = NULL;
+       prev    = NULL;
+
+       for (vp = request->packet->vps; vp; vp = vp->next) {
+               if (vp->attribute == PW_PROXY_STATE) {
+                       prev = x;
+                       last = vp;
+               }
+               x = vp;
+       }
+       if (last && last->strvalue) {
+               /*
+                *      Merit really rapes the Proxy-State attribute.
+                *      See if it still is a valid 4-digit hex number.
+                */
+               s = last->strvalue;
+               if (strlen(s) == 4 && isxdigit(s[0]) && isxdigit(s[1]) &&
+                   isxdigit(s[2]) && isxdigit(s[3])) {
+                       pp = strtol(last->strvalue, NULL, 16);
+               } else {
+                       log(L_PROXY, "server %s mangled Proxy-State attribute",
+                       client_name(request->packet->src_ipaddr));
+               }
+       }
+
+       /*
+        *      Now find it in the list of outstanding requests.
+        */
+
+       for (oldreq = proxy_requests; oldreq; oldreq = oldreq->next) {
+               /*
+                *      Some servers drop the proxy pair. So
+                *      compare in another way if needed.
+                */
+               if (pp >= 0 && pp == oldreq->proxy->id)
+                       break;
+               if (pp < 0 &&
+                   request->packet->src_ipaddr == oldreq->proxy->dst_ipaddr &&
+                   request->packet->id     == (oldreq->proxy->id & 0xFF))
+                       break;
+               lastreq = oldreq;
+       }
+
+       if (oldreq == NULL) {
+               log(L_PROXY, "Unreckognized proxy reply from server %s - ID %d",
+                       client_name(request->packet->src_ipaddr),
+                       request->packet->id);
+               return -1;
+       }
+
+       /*
+        *      Remove oldreq from list.
+        */
+       if (lastreq)
+               lastreq->next = oldreq->next;
+       else
+               proxy_requests = oldreq->next;
+
+       /*
+        *      Remove proxy pair from list.
+        */
+       if (last) {
+               if (prev)
+                       prev->next = last->next;
+               else
+                       request->packet->vps = last->next;
+       }
+
+       /*
+        *      Only allow some attributes to be propagated from
+        *      the remote server back to the NAS, for security.
+        */
+       allowed_pairs = NULL;
+       for(i = 0; allowed[i]; i++)
+               pairmove2(&allowed_pairs, &(request->packet->vps), allowed[i]);
+
+       /*
+        *      Now rebuild the AUTHREQ struct, so that the
+        *      normal functions can process it.
+        */
+       request->proxy = oldreq->proxy;
+       oldreq->proxy = NULL;
+       request->proxy->vps  = allowed_pairs;
+       request->proxy->code = request->packet->code;
+
+       pairfree(request->packet->vps);
+       free(request->packet);
+       request->packet = oldreq->packet;
+       oldreq->packet = NULL;
+
+       request->timestamp = oldreq->timestamp;
+
+       request_free(oldreq);
+
+       return 0;
+}
+
diff --git a/src/main/radclient.c b/src/main/radclient.c
new file mode 100644 (file)
index 0000000..097e106
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * radclient   General radius packet debug tool.
+ *
+ * Version:    @(#)radclient  1.10  25-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+#include       "autoconf.h"
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <unistd.h>
+#include       <string.h>
+#include       <getopt.h>
+#include       <ctype.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+
+#include       "conf.h"
+#include       "libradius.h"
+
+/*
+ *     Read valuepairs from stdin up to End-Of-File.
+ */
+VALUE_PAIR *readvp(void)
+{
+       char            buf[128];
+       int             eol;
+       char            *p;
+       VALUE_PAIR      *vp;
+       VALUE_PAIR      *list;
+       int             error = 0;
+
+       list = NULL;
+
+       while (!error && fgets(buf, 128, stdin) != NULL) {
+
+               p = buf;
+               do {
+                       if ((vp = pairread(&p, &eol)) == NULL) {
+                               librad_perror("radclient");
+                               error = 1;
+                               break;
+                       }
+                       pairadd(&list, vp);
+               } while (!eol);
+       }
+       return error ? NULL: list;
+}
+
+void usage(void)
+{
+       fprintf(stderr, "Usage: radclient [-dn] server acct|auth <secret>\n");
+       exit(1);
+}
+
+int main(int argc, char **argv)
+{
+       RADIUS_PACKET   *req;
+       RADIUS_PACKET   *rep;
+       VALUE_PAIR      *vp;
+       char            *p;
+       char            *secret = "secret";
+       int             do_output = 1;
+       int             c;
+       int             port = 0;
+       int             s;
+
+       if (dict_init(RADDBDIR, RADIUS_DICTIONARY) < 0) {
+               librad_perror("radclient");
+               return 1;
+       }
+
+       while ((c = getopt(argc, argv, "dn")) != EOF) switch(c) {
+               case 'd':
+                       librad_debug = 1;
+                       break;
+               case 'n':
+                       do_output = 0;
+                       break;
+               default:
+                       usage();
+                       break;
+       }
+       argc -= (optind - 1);
+       argv += (optind - 1);
+
+       if (argc < 4)
+               usage();
+
+       if ((req = rad_alloc(1)) == NULL) {
+               librad_perror("radclient");
+               exit(1);
+       }
+       req->id = getpid() & 0xFF;
+
+       /*
+        *      Strip port from hostname if needed.
+        */
+       if ((p = strchr(argv[1], ':')) != NULL) {
+               *p++ = 0;
+               port = atoi(p);
+       }
+
+       /*
+        *      See what kind of request we want to send.
+        */
+       if (strcmp(argv[2], "auth") == 0) {
+               if (port == 0) port = 1645;
+               req->code = PW_AUTHENTICATION_REQUEST;
+       } else if (strcmp(argv[2], "acct") == 0) {
+               if (port == 0) port = 1646;
+               req->code = PW_ACCOUNTING_REQUEST;
+       } else if (isdigit(argv[2][0])) {
+               if (port == 0) port = 1645;
+               port = atoi(argv[2]);
+       } else
+               usage();
+
+       /*
+        *      Resolve hostname.
+        */
+       req->dst_port = port;
+       req->dst_ipaddr = ip_getaddr(argv[1]);
+       if (req->dst_ipaddr == 0) {
+               librad_perror("radclient: %s: ", argv[1]);
+               exit(1);
+       }
+
+       /*
+        *      Add the secret.
+        */
+       if (argv[3]) secret = argv[3];
+
+       /*
+        *      Read valuepairs.
+        */
+       if ((req->vps = readvp()) == NULL)
+               exit(1);
+
+       /*
+        *      Find the password pair and encode it.
+        */
+       if ((vp = pairfind(req->vps, PW_PASSWORD)) != NULL)
+               rad_pwencode(vp->strvalue, &(vp->length), secret, req->vector);
+
+       /*
+        *      Send request.
+        */
+       if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+               perror("radclient: socket: ");
+               exit(1);
+       }
+       rad_send(req, s, secret);
+
+       /*
+        *      And wait for reply.
+        */
+       rep = rad_recv(s);
+       if (rep == NULL)
+               exit(1);
+
+       if (rad_decode(rep, secret) != 0) {
+               librad_perror("rad_decode");
+               exit(1);
+       }
+
+       if (do_output)
+               vp_printlist(stdout, rep->vps);
+
+       return 0;
+}
+
diff --git a/src/main/radiusd.c b/src/main/radiusd.c
new file mode 100644 (file)
index 0000000..e4725b3
--- /dev/null
@@ -0,0 +1,810 @@
+/*
+ * radiusd.c   Main loop of the radius server.
+ *
+ * Version:    @(#)radiusd.c  1.90  22-Jul-1999  miquels@cistron.nl
+ *
+ */
+
+/* don't look here for the version, run radiusd -v or look in version.c */
+char radiusd_sccsid[] =
+"@(#)radiusd.c 1.90 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <sys/file.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <netdb.h>
+#include       <fcntl.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <unistd.h>
+#include       <signal.h>
+#include       <errno.h>
+#include       <sys/wait.h>
+#if HAVE_GETOPT_H
+#  include     <getopt.h>
+#endif
+#if HAVE_SYS_SELECT_H
+#  include     <sys/select.h>
+#endif
+
+#include       "radiusd.h"
+
+/*
+ *     Global variables.
+ */
+char                   *progname;
+char                   *radius_dir;
+char                   *radacct_dir;
+char                   *radlog_dir;
+int                    log_stripped_names;
+int                    cache_passwd = 0;
+int                    debug_flag;
+int                    use_dbm = 0;
+UINT4                  myip = 0;
+int                    log_auth_detail = 0;
+int                    log_auth = 0;
+int                    log_auth_pass  = 0;
+int                    auth_port;
+int                    acct_port;
+
+static int             got_chld = 0;
+static int             request_list_busy = 0;
+static int             sockfd;
+static int             acctfd;
+static int             spawn_flag;
+static int             acct_pid;
+static int             radius_pid;
+static int             need_reload = 0;
+static REQUEST         *first_request;
+
+#if !defined(__linux__) && !defined(__GNU_LIBRARY__)
+extern int     errno;
+#endif
+
+typedef                int (*FUNP)(REQUEST *, int);
+
+static void    usage(void);
+
+static void    sig_fatal (int);
+static void    sig_hup (int);
+
+static int     radrespond (REQUEST *, int);
+static void    rad_spawn_child (REQUEST *, int, FUNP);
+
+/*
+ *     Read config files.
+ */
+static void reread_config(int reload)
+{
+       int res = 0;
+       int pid = getpid();
+
+       if (!reload) {
+               log(L_INFO, "Starting - reading configuration files ...");
+       } else if (pid == radius_pid) {
+               log(L_INFO, "Reloading configuration files.");
+       }
+
+       /* Read users file etc. */
+       if (res == 0 && read_config_files() != 0)
+               res = -1;
+
+       if (res != 0) {
+         if (pid == radius_pid) {
+                       log(L_ERR|L_CONS,
+                               "Errors reading config file - EXITING");
+                       if (acct_pid) {
+                               signal(SIGCHLD, SIG_DFL);
+                               kill(acct_pid, SIGTERM);
+                       }
+               }
+               exit(1);
+       }
+}
+
+
+int main(int argc, char **argv)
+{
+       CLIENT                  *cl;
+       REQUEST                 *request;
+       RADIUS_PACKET           *packet;
+#ifdef RADIUS_PID
+       FILE                    *fp;
+#endif
+       struct  sockaddr        salocal;
+       struct  sockaddr_in     *sin;
+       struct  servent         *svp;
+       fd_set                  readfds;
+       int                     result;
+       int                     argval;
+       int                     t;
+       int                     pid;
+       int                     i;
+       int                     fd = 0;
+       int                     status;
+       int                     dontfork = 0;
+       int                     radius_port = 0;
+
+#ifdef OSFC2
+       set_auth_parameters(argc,argv);
+#endif
+
+       if ((progname = strrchr(argv[0], '/')) == NULL)
+               progname = argv[0];
+       else
+               progname++;
+
+       debug_flag = 0;
+       spawn_flag = 1;
+       radacct_dir = RADACCT_DIR;
+       radius_dir = RADIUS_DIR;
+       radlog_dir = RADLOG_DIR;
+
+       signal(SIGHUP, sig_hup);
+       signal(SIGINT, sig_fatal);
+       signal(SIGQUIT, sig_fatal);
+       signal(SIGTRAP, sig_fatal);
+       signal(SIGIOT, sig_fatal);
+       signal(SIGTERM, sig_fatal);
+       signal(SIGCHLD, sig_cleanup);
+#if 0
+       signal(SIGFPE, sig_fatal);
+       signal(SIGSEGV, sig_fatal);
+       signal(SIGILL, sig_fatal);
+#endif
+
+       /*
+        *      Close unused file descriptors.
+        */
+       for (t = 32; t >= 3; t--)
+                       close(t);
+
+       /*
+        *      Process the options.
+        */
+       while((argval = getopt(argc, argv, "ASa:ci:l:d:bfp:svxyz")) != EOF) {
+
+               switch(argval) {
+
+               case 'A':
+                       log_auth_detail++;
+                       break;
+
+               case 'a':
+                       radacct_dir = optarg;
+                       break;
+               
+#if defined(WITH_DBM) || defined(WITH_NDBM)
+               case 'b':
+                       use_dbm++;
+                       break;
+#endif
+               case 'c':
+                       cache_passwd = 1;
+                       break;
+
+               case 'd':
+                       radius_dir = optarg;
+                       break;
+               
+               case 'f':
+                       dontfork = 1;
+                       break;
+
+               case 'i':
+                       if ((myip = ip_getaddr(optarg)) == 0) {
+                               fprintf(stderr, "radiusd: %s: host unknown\n",
+                                       optarg);
+                               exit(1);
+                       }
+                       break;
+               
+               case 'l':
+                       radlog_dir = optarg;
+                       break;
+               
+               case 'S':
+                       log_stripped_names++;
+                       break;
+
+               case 'p':
+                       radius_port = atoi(optarg);
+                       break;
+
+               case 's':       /* Single process mode */
+                       spawn_flag = 0;
+                       break;
+
+               case 'v':
+                       version();
+                       break;
+
+               case 'x':
+                       debug_flag++;
+                       librad_debug++;
+                       break;
+               
+               case 'y':
+                       log_auth = 1;
+                       break;
+
+               case 'z':
+                       log_auth_pass = 1;
+                       break;
+
+               default:
+                       usage();
+                       break;
+               }
+       }
+
+       /*
+        *      Open Authentication socket.
+        */
+       svp = getservbyname ("radius", "udp");
+       if (radius_port)
+               auth_port = radius_port;
+       else if (svp != NULL)
+               auth_port = ntohs(svp->s_port);
+       else
+               auth_port = PW_AUTH_UDP_PORT;
+
+       sockfd = socket (AF_INET, SOCK_DGRAM, 0);
+       if (sockfd < 0) {
+               perror("auth socket");
+               exit(1);
+       }
+
+       sin = (struct sockaddr_in *) & salocal;
+        memset ((char *) sin, '\0', sizeof (salocal));
+       sin->sin_family = AF_INET;
+       sin->sin_addr.s_addr = myip ? myip : INADDR_ANY;
+       sin->sin_port = htons(auth_port);
+
+       result = bind (sockfd, & salocal, sizeof (*sin));
+       if (result < 0) {
+               perror ("auth bind");
+               exit(1);
+       }
+
+       /*
+        *      Open Accounting Socket.
+        */
+       svp = getservbyname ("radacct", "udp");
+       if (radius_port || svp == (struct servent *) 0)
+               acct_port = auth_port + 1;
+       else
+               acct_port = ntohs(svp->s_port);
+       
+       acctfd = socket (AF_INET, SOCK_DGRAM, 0);
+       if (acctfd < 0) {
+               perror ("acct socket");
+               exit(1);
+       }
+
+       sin = (struct sockaddr_in *) & salocal;
+        memset ((char *) sin, '\0', sizeof (salocal));
+       sin->sin_family = AF_INET;
+       sin->sin_addr.s_addr = myip ? myip : INADDR_ANY;
+       sin->sin_port = htons(acct_port);
+
+       result = bind (acctfd, & salocal, sizeof (*sin));
+       if (result < 0) {
+               perror ("acct bind");
+               exit(1);
+       }
+
+       radius_pid = getpid();
+#ifdef RADIUS_PID
+       if ((fp = fopen(RADIUS_PID, "w")) != NULL) {
+               fprintf(fp, "%d\n", radius_pid);
+               fclose(fp);
+       }
+#endif
+       /*
+        *      Read config files.
+        */
+       reread_config(0);
+
+       /*
+        *      Register built-in compare functions.
+        */
+       pair_builtincompare_init();
+
+       /*
+        *      Disconnect from session
+        */
+       if(debug_flag == 0 && dontfork == 0) {
+               pid = fork();
+               if(pid < 0) {
+                       log(L_ERR|L_CONS, "Couldn't fork");
+                       exit(1);
+               }
+               if(pid > 0) {
+                       exit(0);
+               }
+#ifdef HAVE_SETSID
+               setsid();
+#endif
+       }
+       /*
+        *      Use linebuffered or unbuffered stdout if
+        *      the debug flag is on.
+        */
+       if (debug_flag) setlinebuf(stdout);
+
+#if !defined(M_UNIX) && !defined(__linux__)
+       /*
+        *      Open system console as stderr
+        */
+       if (!debug_flag) {
+               t = open("/dev/console", O_WRONLY | O_NOCTTY);
+               if (t != 2) {
+                       dup2(t, 2);
+                       close(t);
+               }
+       }
+#endif
+       /*
+        *      If we are in forking mode, we will start a child
+        *      to listen for Accounting requests.  If not, we will 
+        *      listen for them ourself.
+        */
+       if (spawn_flag) {
+               acct_pid = fork();
+               if(acct_pid < 0) {
+                       log(L_ERR|L_CONS, "Couldn't fork");
+                       exit(1);
+               }
+               if(acct_pid > 0) {
+                       close(acctfd);
+                       acctfd = -1;
+                       log(L_INFO, "Ready to process requests.");
+               }
+               else {
+                       close(sockfd);
+                       sockfd = -1;
+               }
+       } else
+               log(L_INFO, "Ready to process requests.");
+
+
+       /*
+        *      Receive user requests
+        */
+       for(;;) {
+
+               if (need_reload) {
+                       reread_config(1);
+                       need_reload = 0;
+                       if (getpid() == radius_pid && acct_pid)
+                               kill(acct_pid, SIGHUP);
+               }
+
+               FD_ZERO(&readfds);
+               if (sockfd >= 0)
+                       FD_SET(sockfd, &readfds);
+               if (acctfd >= 0)
+                       FD_SET(acctfd, &readfds);
+
+               status = select(32, &readfds, NULL, NULL, NULL);
+               if (status == -1) {
+                       if (errno == EINTR)
+                               continue;
+                       sig_fatal(101);
+               }
+               for (i = 0; i < 2; i++) {
+
+                       if (i == 0) fd = sockfd;
+                       if (i == 1) fd = acctfd;
+                       if (fd < 0 || !FD_ISSET(fd, &readfds))
+                               continue;
+
+                       packet = rad_recv(fd);
+                       if (packet == NULL) continue;
+
+                       /*
+                        *      See if we know this client.
+                        */
+                       if ((cl = client_find(packet->src_ipaddr)) == NULL) {
+                               log(L_ERR, "request from unknown client: %s",
+                                       ip_hostname(packet->src_ipaddr));
+                                       rad_free(packet);
+                                       continue;
+                       }
+                       if (rad_decode(packet, cl->secret) != 0) {
+                               log(L_ERR, "%s", librad_errstr);
+                               rad_free(packet);
+                               continue;
+                       }
+                       if ((request = malloc(sizeof(REQUEST))) == NULL) {
+                               log(L_ERR|L_CONS, "no memory");
+                               exit(1);
+                       }
+                       memset(request, 0, sizeof(REQUEST));
+                       request->packet = packet;
+                       request->timestamp = time(NULL);
+                       strcpy(request->secret, cl->secret);
+                       radrespond(request, fd);
+               }
+       }
+}
+
+
+/*
+ *     Respond to supported requests:
+ *
+ *             PW_AUTHENTICATION_REQUEST - Authentication request from
+ *                             a client network access server.
+ *
+ *             PW_ACCOUNTING_REQUEST - Accounting request from
+ *                             a client network access server.
+ *
+ *             PW_AUTHENTICATION_ACK
+ *             PW_AUTHENTICATION_REJECT
+ *             PW_ACCOUNTING_RESPONSE - Reply from a remote Radius server.
+ *                             Relay reply back to original NAS.
+ *
+ */
+int radrespond(REQUEST *request, int activefd)
+{
+       int dospawn;
+       FUNP fun;
+       VALUE_PAIR *namepair;
+       int e;
+
+       dospawn = 0;
+       fun = NULL;
+
+       /*
+        *      First, see if we need to proxy this request.
+        */
+       switch(request->packet->code) {
+
+       case PW_AUTHENTICATION_REQUEST:
+       case PW_ACCOUNTING_REQUEST:
+               /*
+                *      Setup username and stuff.
+                */
+               if ((e = rad_mangle(request)) < 0)
+                       return e;
+               namepair = pairfind(request->packet->vps, PW_USER_NAME);
+               if (namepair == NULL)
+                       break;
+               /*
+                *      We always call proxy_send, it returns non-zero
+                *      if it did actually proxy the request.
+                */
+               if (proxy_send(request, activefd) != 0)
+                       return 0;
+               break;
+
+       case PW_AUTHENTICATION_ACK:
+       case PW_AUTHENTICATION_REJECT:
+       case PW_ACCOUNTING_RESPONSE:
+               if (proxy_receive(request, activefd) < 0)
+                       return 0;
+               break;
+       }
+
+       /*
+        *      Select the required function and indicate if
+        *      we need to fork off a child to handle it.
+        */
+       switch(request->packet->code) {
+
+       case PW_AUTHENTICATION_REQUEST:
+               dospawn = spawn_flag;
+               fun = rad_authenticate;
+               break;
+       
+       case PW_ACCOUNTING_REQUEST:
+               fun = rad_accounting;
+               break;
+       
+       case PW_PASSWORD_REQUEST:
+               /*
+                *      FIXME: print an error message here.
+                *      We don't support this anymore.
+                */
+               /* rad_passchange(request, activefd); */
+               break;
+       
+
+       default:
+               break;
+       }
+
+       /*
+        *      If we did select a function, execute it
+        *      (perhaps through rad_spawn_child)
+        */
+       if (fun) {
+               if (dospawn)
+                       rad_spawn_child(request, activefd, fun);
+               else {
+                       (*fun)(request, activefd);
+                       request_free(request);
+               }
+       }
+
+       return 0;
+}
+
+
+/*
+ *     Spawns child processes to perform authentication/accounting
+ *     and respond to RADIUS clients.  This functions also
+ *     cleans up complete child requests, and verifies that there
+ *     is only one process responding to each request (duplicate
+ *     requests are filtered out).
+ */
+static void rad_spawn_child(REQUEST *request, int activefd, FUNP fun)
+{
+       REQUEST         *curreq;
+       REQUEST         *prevreq;
+       RADIUS_PACKET   *pkt;
+       UINT4           curtime;
+       int             request_count;
+       int             child_pid;
+
+       curtime = (UINT4)time(NULL);
+       request_count = 0;
+       curreq = first_request;
+       prevreq = (REQUEST *)NULL;
+       pkt = request->packet;
+
+       /*
+        *      When mucking around with the request list, we block
+        *      asynchronous access (through the SIGCHLD handler) to
+        *      the list - equivalent to sigblock(SIGCHLD).
+        */
+       request_list_busy = 1;
+
+       while(curreq != (REQUEST *)NULL) {
+               if (curreq->child_pid == -1 &&
+                   curreq->timestamp + CLEANUP_DELAY <= curtime) {
+                       /*
+                        *      Request completed, delete it
+                        */
+                       if (prevreq == (REQUEST *)NULL) {
+                               first_request = curreq->next;
+                               request_free(curreq);
+                               curreq = first_request;
+                       } else {
+                               prevreq->next = curreq->next;
+                               request_free(curreq);
+                               curreq = prevreq->next;
+                       }
+               } else if (curreq->packet->src_ipaddr == pkt->src_ipaddr &&
+                          curreq->packet->id == pkt->id) {
+                       /*
+                        *      Compare the request vectors to see
+                        *      if it really is the same request.
+                        */
+                       if (!memcmp(curreq->packet->vector, pkt->vector, 16)) {
+                               /*
+                                * This is a duplicate request - just drop it
+                                */
+                               log(L_ERR,
+                               "Dropping duplicate authentication packet"
+                               " from client %s - ID: %d",
+                               client_name(request->packet->src_ipaddr),
+                               request->packet->id);
+
+                               request_free(request);
+                               request_list_busy = 0;
+                               sig_cleanup(SIGCHLD);
+
+                               return;
+                       }
+                       /*
+                        *      If the old request was completed,
+                        *      delete it right now.
+                        */
+                       if (curreq->child_pid == -1) {
+                               curreq->timestamp = curtime - CLEANUP_DELAY;
+                               continue;
+                       }
+
+                       /*
+                        *      Not completed yet, do nothing special.
+                        */
+                       prevreq = curreq;
+                       curreq = curreq->next;
+                       request_count++;
+               } else {
+                       if (curreq->timestamp + MAX_REQUEST_TIME <= curtime &&
+                           curreq->child_pid != -1) {
+                               /*
+                                *      This request seems to have hung -
+                                *      kill it
+                                */
+                               child_pid = curreq->child_pid;
+                               log(L_ERR,
+                                       "Killing unresponsive child pid %d",
+                                                               child_pid);
+                               curreq->child_pid = -1;
+                               kill(child_pid, SIGTERM);
+                       }
+                       prevreq = curreq;
+                       curreq = curreq->next;
+                       request_count++;
+               }
+       }
+
+       /*
+        *      This is a new request
+        */
+       if (request_count > MAX_REQUESTS) {
+               log(L_ERR, "Dropping request (too many): "
+                               "from client %s - ID: %d",
+                               client_name(request->packet->src_ipaddr),
+                               request->packet->id);
+               request_free(request);
+
+               request_list_busy = 0;
+               sig_cleanup(SIGCHLD);
+                               
+               return;
+       }
+
+       /*
+        *      Add this request to the list
+        */
+       request->next = (REQUEST *)NULL;
+       request->child_pid = -1;
+       request->timestamp = curtime;
+
+       if (prevreq == (REQUEST *)NULL)
+               first_request = request;
+       else
+               prevreq->next = request;
+
+       /*
+        *      fork our child
+        */
+       if ((child_pid = fork()) < 0) {
+               log(L_ERR, "Fork failed for request from nas %s - ID: %d",
+                               nas_name2(request->packet),
+                               request->packet->id);
+       }
+       if (child_pid == 0) {
+               /*
+                *      This is the child, it should go ahead and respond
+                */
+               request_list_busy = 0;
+               signal(SIGCHLD, SIG_DFL);
+               (*fun)(request, activefd);
+               exit(0);
+       }
+
+       /*
+        *      Register the Child
+        */
+       request->child_pid = child_pid;
+
+       request_list_busy = 0;
+       sig_cleanup(SIGCHLD);
+}
+
+
+/*ARGSUSED*/
+void sig_cleanup(int sig)
+{
+       int             status;
+        pid_t          pid;
+       REQUEST *curreq;
+       /*
+        *      request_list_busy is a lock on the request list
+        */
+       if (request_list_busy) {
+               got_chld = 1;
+               return;
+       }
+       got_chld = 0;
+
+       /*
+        *      There are reports that this line on Solaris 2.5.x
+        *      caused trouble. Should be fixed now that Solaris
+        *      [defined(sun) && defined(__svr4__)] has it's own
+        *      sun_signal() function.
+        */
+       signal(SIGCHLD, sig_cleanup);
+
+        for (;;) {
+               pid = waitpid((pid_t)-1, &status, WNOHANG);
+                if (pid <= 0)
+                        return;
+
+               if (pid == acct_pid)
+                       sig_fatal(100);
+
+               curreq = first_request;
+               while (curreq != (REQUEST *)NULL) {
+                       if (curreq->child_pid == pid) {
+                               curreq->child_pid = -1;
+                               /*
+                                *      FIXME: UINT4 ?
+                                */
+                               curreq->timestamp = (UINT4)time(NULL);
+                               break;
+                       }
+                       curreq = curreq->next;
+               }
+        }
+}
+
+/*
+ *     Display the syntax for starting this program.
+ */
+static void usage(void)
+{
+       fprintf(stderr,
+#if defined(WITH_DBM) || defined(WITH_NDBM)
+               "Usage: %s [-a acct_dir] [-d db_dir] [-l logdir] [-bcsxyz]\n",
+#else
+               "Usage: %s [-a acct_dir] [-d db_dir] [-l logdir] [-csxyz]\n",
+#endif
+               progname);
+       exit(1);
+}
+
+
+/*
+ *     We got a fatal signal. Clean up and exit.
+ */
+static void sig_fatal(int sig)
+{
+       char *me = "MASTER: ";
+
+       if (radius_pid == getpid()) {
+               /*
+                *      FIXME: kill all children, not only the
+                *      accounting process. Oh well..
+                */
+               if (acct_pid > 0)
+                       kill(acct_pid, SIGKILL);
+       } else {
+               me = "CHILD: ";
+       }
+
+       switch(sig) {
+               case 100:
+                       log(L_ERR, "%saccounting process died - exit.", me);
+                       break;
+               case 101:
+                       log(L_ERR, "%sfailed in select() - exit.", me);
+                       break;
+               case SIGTERM:
+                       log(L_INFO, "%sexit.", me);
+                       break;
+               default:
+                       log(L_ERR, "%sexit on signal (%d)", me, sig);
+                       break;
+       }
+
+       exit(sig == SIGTERM ? 0 : 1);
+}
+
+
+/*
+ *     We got the hangup signal.
+ *     Re-read the configuration files.
+ */
+/*ARGSUSED*/
+static void sig_hup(int sig)
+{
+       signal(SIGHUP, sig_hup);
+       need_reload = 1;
+}
+
diff --git a/src/main/radlast.in b/src/main/radlast.in
new file mode 100755 (executable)
index 0000000..0bf667f
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+prefix         = @prefix@
+localstatedir  = @localstatedir@
+logdir         = @logdir@
+
+exec last -f $logdir/radwtmp "$@"
diff --git a/src/main/radtest.in b/src/main/radtest.in
new file mode 100644 (file)
index 0000000..997f802
--- /dev/null
@@ -0,0 +1,46 @@
+#! /bin/sh
+#
+# radtest      Emulate the user interface of the old
+#              radtest that used to be part of cistron-radius.
+#
+# Version:     @(#)radtest.sh  1.10  25-Jul-1999  miquels@cistron.nl
+#
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+bindir="@bindir@"
+
+usage() {
+       echo "Usage: radtest user passwd radius-server nas-port-id secret [ppphint] [nasname]" >&2
+       exit 1
+}
+
+radclient=$bindir/radclient
+if [ ! -x "$radclient" ] && [ -x ./radclient ]
+then
+       radclient=./radclient
+fi
+
+if [ $# -lt 5 ] || [ $# -gt 7 ]
+then
+       usage
+fi
+
+if [ "$7" ]
+then
+       nas=$7
+else
+       nas=`hostname`
+fi
+
+(
+       echo "User-Name = \"$1\""
+       echo "Password = \"$2\""
+       echo "NAS-IP-Address = $nas"
+       echo "NAS-Port-Id = $4"
+       if [ "$6" ]
+       then
+               echo "Framed-Protocol = PPP"
+       fi
+) | $radclient -dn $3 auth $5
+
diff --git a/src/main/raduse.c b/src/main/raduse.c
new file mode 100644 (file)
index 0000000..0dcc3c0
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * raduse      Shows the usage of the modem lines on a terminal server.
+ *
+ * Version:    @(#)raduse  1.12  30-Jun-1999  miquels@cistron.nl
+ *
+ */
+
+#include "autoconf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include "sysutmp.h"
+#include "conf.h"
+
+#ifdef __svr4__
+#  define ut_time ut_xtime
+#endif
+
+#define UTSIZE (sizeof(struct utmp))
+
+#define HOURS 19
+
+#define MAXLINES 64
+
+struct line {
+  time_t lastout;
+  time_t inuse;
+  char hour[HOURS];
+};
+struct line lines[MAXLINES];
+int nrlines = 35;
+
+/*
+ *     List the terminal servers in the logfile.
+ */
+void listnas(void)
+{
+  FILE *fp;
+  FILE *pp;
+  time_t now, stop;
+  struct utmp ut;
+  char *p;
+  int first = 1;
+  char buf[128];
+  int found = 0;
+
+  /* Open the sort pipe. */
+  pp = popen("sort -u", "w");
+
+  /* Go back max. 1 day. */
+  time(&now);
+  stop = now - 3600 * HOURS;
+
+  /* Open wtmp file. */
+  if ((fp = fopen(RADWTMP, "r")) == NULL) {
+       perror(RADWTMP);
+       exit(1);
+  }
+  fseek(fp, -UTSIZE, SEEK_END);
+
+  /* Read structs backwards. */
+  while(1) {
+       /* Rewind if needed. */
+       if (!first && fseek(fp, -2 * UTSIZE, SEEK_CUR) < 0) break;
+       first = 0;
+
+       /* Read struct and see if we have to stop. */
+       if (ftell(fp) < UTSIZE) break;
+       fread(&ut, UTSIZE, 1, fp);
+       if (ut.ut_time < stop) break;
+
+       memset(buf, 0, sizeof(buf));
+       strncpy(buf, ut.ut_line, sizeof(ut.ut_line));
+
+       /* Get terminal server name. */
+       if ((p = strchr(buf, ':')) != NULL)
+               p++;
+       else
+               p = buf + 2;
+       fprintf(pp, "%s\n", p);
+       found = 1;
+  }
+  fclose(fp);
+  pclose(pp);
+
+  if (found == 0)
+       printf("raduse: no data found over the last 24 hours.\n");
+}
+
+/*
+ * Find out the usage of the ttys defined in
+ * struct line lines[] for the last 21 hours.
+ */
+int fillstruct(int offset, char *nas)
+{
+  FILE *fp;
+  time_t now, stop;
+  struct utmp ut;
+  int i, n, port;
+  int beg, end;
+  char *p;
+  int first = 1;
+  char buf[128];
+  int found = 0;
+
+  /* Go back max. 1 day. */
+  time(&now);
+  stop = now - 3600 * HOURS;
+
+  /* Open wtmp file. */
+  if ((fp = fopen(RADWTMP, "r")) == NULL) {
+       perror(RADWTMP);
+       exit(1);
+  }
+  fseek(fp, -UTSIZE, SEEK_END);
+
+  /* Read structs backwards. */
+  while(1) {
+       /* Rewind if needed. */
+       if (!first && fseek(fp, -2 * UTSIZE, SEEK_CUR) < 0) break;
+       first = 0;
+
+       /* Read struct and see if we have to stop. */
+       if (ftell(fp) < UTSIZE) break;
+       fread(&ut, UTSIZE, 1, fp);
+       if (ut.ut_time < stop) break;
+
+       memset(buf, 0, sizeof(buf));
+       strncpy(buf, ut.ut_line, sizeof(ut.ut_line));
+
+       /* Compare terminal server name. */
+       if ((p = strchr(buf, ':')) != NULL)
+               p++;
+       else
+               p = buf + 2;
+       if (strcmp(p, nas) != 0)
+               continue;
+
+       found = 1;
+
+       /* Now see which tty this was. */
+       if ((p = strchr(buf, ':')) != NULL)
+               *p = 0;
+       else
+               buf[2] = 0;
+
+       port = atoi(buf);
+       if (port == 0 && buf[0] != '0')
+               continue;
+       if (port < offset || port > offset + nrlines)
+               continue;
+
+       i = port - offset;
+
+       /* Login or logout? */
+       if (ut.ut_user[0] == 0) {
+               lines[i].lastout = ut.ut_time;
+               continue;
+       }
+
+       /* Skip type LOGIN */
+       if (strncmp(ut.ut_user, "LOGIN", 5) == 0)
+               continue;
+
+       /* A login. Fill out the hour string. */
+       beg = (now - ut.ut_time) / 3600;
+       if (lines[i].lastout == 0) {
+               lines[i].inuse = 1;
+               end = 0;
+       } else
+               end = (now - lines[i].lastout) / 3600;
+       if (beg >= HOURS) beg = HOURS - 1;
+       if (end >= HOURS) end = HOURS - 1;
+
+       for(n = end; n <= beg; n++)
+               lines[i].hour[n] = lines[i].lastout ? '*' : '@';
+
+  }
+  fclose(fp);
+
+  return found ? 0 : -1;
+}
+
+/*
+ * Draw something that vaguely resembles a graph showing the
+ * usage of the tty lines over the last 21 hours.
+ */
+void drawit(int wide, int offset)
+{
+  time_t now;
+  int i, n, hour;
+  struct tm *tm;
+  int thishour;
+  int star;
+
+  /* Find out current time. */
+  time(&now);
+  tm = localtime(&now);
+  thishour = tm->tm_hour;
+
+  /* Change lower spaces to dots. */
+  for(i = 0; i < nrlines; i++) {
+       n = 0;
+       for(hour = 0; hour < HOURS; hour++) {
+               if (lines[i].hour[hour]) {
+                       n = 1;
+               } else if (n)
+                       lines[i].hour[hour] = '.';
+       }
+  }
+
+  /* Prefix (show if line is in use now) */
+  printf("now|");
+  for(i = 0; i < nrlines; i++) {
+       if (wide)
+               printf(" %c ", lines[i].inuse ? '@' : ' ');
+       else
+               printf("%c ", lines[i].inuse ? '@' : ' ');
+  }
+  printf("\n");
+
+  /* Last 21 hours. */
+  for(hour = 0; hour < HOURS; hour++) {
+       printf("%02d |", thishour);
+       thishour--;
+       if (thishour < 0) thishour = 23;
+
+       for(i = 0; i < nrlines; i++) {
+               star = ' ';
+               if (lines[i].hour[hour])
+                       star = lines[i].hour[hour];
+               if (wide)
+                       printf(" %c ", star);
+               else
+                       printf("%c ", star);
+       }
+       /* EOL */
+       printf("\n");
+  }
+
+  /* Print a short suffix. */
+  printf("---+");
+  for(i = 0; i < nrlines; i++)
+       printf(wide ? "---" : "--");
+  printf("\n   |");
+  for(i = 0; i < nrlines; i++) {
+       if (wide)
+               printf("%02d|", i + offset);
+       else
+               printf("%d|", (i + offset) / 10);
+  }
+  if (!wide) {
+       printf("\n   |");
+       for(i = 0; i < nrlines; i++)
+               printf("%d|", (i + offset) % 10);
+  }
+  printf("\n");
+}
+
+void usage()
+{
+  fprintf(stderr, "Usage: raduse [-w] [-o offset] terminal-server\n");
+  fprintf(stderr, "       use raduse -l to find out a list of terminal servers\n");
+  exit(1);
+}
+
+int main(int argc, char **argv)
+{
+  int wide = 0;
+  int c;
+  int offset = 0;
+  int list = 0;
+
+  while((c = getopt(argc, argv, "lwo:")) != EOF) switch(c) {
+       case 'w':
+               wide = 1;
+               break;
+       case 'o':
+               offset = atoi(optarg);
+               break;
+       case 'l':
+               list = 1;
+               break;
+       default:
+               usage();
+               break;
+  }
+
+  if (list) {
+       listnas();
+       exit(0);
+  }
+
+  if (wide) nrlines = 25;
+
+  if (optind >= argc) usage();
+
+  if (fillstruct(offset, argv[optind]) < 0) {
+       fprintf(stderr,
+   "raduse: %s: no data found (over the last 24 hours) (try raduse -l).\n",
+               argv[optind]);
+       return 1;
+  }
+  drawit(wide, offset);
+
+  return 0;
+}
+
diff --git a/src/main/radutmp.c b/src/main/radutmp.c
new file mode 100644 (file)
index 0000000..a39653e
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ * radutmp.c   Radius session management.
+ *
+ * Version:    @(#)radutmp.c  1.00  10--Aug-1999  miquels@cistron.nl
+ *
+ */
+char radutmp_sccsid[] =
+"@(#)radutmp.c 1.00  Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <sys/file.h>
+#include       <sys/stat.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <fcntl.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <netdb.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <unistd.h>
+#include       <signal.h>
+#include       <errno.h>
+#include       <sys/wait.h>
+
+#if HAVE_MALLOC_H
+#  include <malloc.h>
+#endif
+
+#include       "radiusd.h"
+#include       "radutmp.h"
+
+static char porttypes[] = "ASITX";
+
+#define LOCK_LEN sizeof(struct radutmp)
+
+/*
+ *     used for caching radutmp lookups.
+ */
+typedef struct nas_port {
+       UINT4                   nasaddr;
+       int                     port;
+       off_t                   offset;
+       struct nas_port         *next;
+} NAS_PORT;
+static NAS_PORT *nas_port_list = NULL;
+
+
+/*
+ *     Lookup a NAS_PORT in the nas_port_list
+ */
+static NAS_PORT *nas_port_find(UINT4 nasaddr, int port)
+{
+       NAS_PORT        *cl;
+
+       for(cl = nas_port_list; cl; cl = cl->next)
+               if (nasaddr == cl->nasaddr &&
+                       port == cl->port)
+                       break;
+       return cl;
+}
+
+
+/*
+ *     Zap a user, or all users on a NAS, from the radutmp file.
+ */
+int radutmp_zap(UINT4 nasaddr, int port, char *user, time_t t)
+{
+       struct radutmp  u;
+       FILE            *fp;
+       int             fd;
+
+       if (t == 0) time(&t);
+       fp = fopen(RADWTMP, "a");
+
+       if ((fd = open(RADUTMP, O_RDWR|O_CREAT, 0644)) >= 0) {
+               int r;
+
+               /*
+                *      Lock the utmp file, prefer lockf() over flock().
+                */
+#if defined(F_LOCK) && !defined(BSD)
+               (void)lockf(fd, F_LOCK, LOCK_LEN);
+#else
+               (void)flock(fd, LOCK_EX);
+#endif
+               /*
+                *      Find the entry for this NAS / portno combination.
+                */
+               r = 0;
+               while (read(fd, &u, sizeof(u)) == sizeof(u)) {
+                       if (((nasaddr != 0 && nasaddr != u.nas_address) ||
+                             (port >= 0   && port    != u.nas_port) ||
+                             (user != NULL && strcmp(u.login, user) != 0) ||
+                              u.type != P_LOGIN))
+                               continue;
+                       /*
+                        *      Match. Zap it.
+                        */
+                       if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
+                               log(L_ERR, "Accounting: radutmp_zap: "
+                                          "negative lseek!\n");
+                               lseek(fd, (off_t)0, SEEK_SET);
+                       }
+                       u.type = P_IDLE;
+                       u.time = t;
+                       write(fd, &u, sizeof(u));
+
+#if 0 /* FIXME: should we fixup radwtmp as well or not ? */
+                       /*
+                        *      Add a logout entry to the wtmp file.
+                        */
+                       if (fp != NULL)  {
+                               make_wtmp(&u, &wt, PW_STATUS_STOP);
+                               fwrite(&wt, sizeof(wt), 1, fp);
+                       }
+#endif
+               }
+               close(fd);
+       }
+       if (fp) fclose(fp);
+
+       return 0;
+}
+
+
+/*
+ *     Store logins in the RADIUS utmp file.
+ */
+int radutmp_add(REQUEST *request)
+{
+       struct radutmp  ut, u;
+       VALUE_PAIR      *vp;
+       int             rb_record = 0;
+       int             status = -1;
+       int             nas_address = 0;
+       int             framed_address = 0;
+       int             protocol = -1;
+       time_t          t;
+       int             fd;
+       int             ret = 0;
+       int             just_an_update = 0;
+       int             port_seen = 0;
+       int             nas_port_type = 0;
+       int             off;
+
+       /*
+        *      Which type is this.
+        */
+       if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE)) == NULL) {
+               log(L_ERR, "Accounting: no Accounting-Status-Type record.");
+               return -1;
+       }
+       status = vp->lvalue;
+       if (status == PW_STATUS_ACCOUNTING_ON ||
+           status == PW_STATUS_ACCOUNTING_OFF) rb_record = 1;
+
+       if (!rb_record &&
+           (vp = pairfind(request->packet->vps, PW_USER_NAME)) == NULL) do {
+               int check1 = 0;
+               int check2 = 0;
+
+               /*
+                *      ComOS (up to and including 3.5.1b20) does not send
+                *      standard PW_STATUS_ACCOUNTING_XXX messages.
+                *
+                *      Check for:  o no Acct-Session-Time, or time of 0
+                *                  o Acct-Session-Id of "00000000".
+                *
+                *      We could also check for NAS-Port, that attribute
+                *      should NOT be present (but we don't right now).
+                */
+               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_TIME))
+                    == NULL || vp->lvalue == 0)
+                       check1 = 1;
+               if ((vp = pairfind(request->packet->vps, PW_ACCT_SESSION_ID))
+                    != NULL && vp->length == 8 &&
+                    memcmp(vp->strvalue, "00000000", 8) == 0)
+                       check2 = 1;
+               if (check1 == 0 || check2 == 0) {
+#if 0 /* Cisco sometimes sends START records without username. */
+                       log(L_ERR, "Accounting: no username in record");
+                       return -1;
+#else
+                       break;
+#endif
+               }
+               log(L_INFO, "Accounting: converting reboot records.");
+               if (status == PW_STATUS_STOP)
+                       status = PW_STATUS_ACCOUNTING_OFF;
+               if (status == PW_STATUS_START)
+                       status = PW_STATUS_ACCOUNTING_ON;
+               rb_record = 1;
+       } while(0);
+
+       time(&t);
+       memset(&ut, 0, sizeof(ut));
+       ut.porttype = 'A';
+
+       /*
+        *      First, find the interesting attributes.
+        */
+       for (vp = request->packet->vps; vp; vp = vp->next) {
+               switch (vp->attribute) {
+                       case PW_USER_NAME:
+                               strncpy(ut.login, vp->strvalue, RUT_NAMESIZE);
+                               break;
+                       case PW_LOGIN_IP_HOST:
+                       case PW_FRAMED_IP_ADDRESS:
+                               framed_address = vp->lvalue;
+                               ut.framed_address = vp->lvalue;
+                               break;
+                       case PW_FRAMED_PROTOCOL:
+                               protocol = vp->lvalue;
+                               break;
+                       case PW_NAS_IP_ADDRESS:
+                               nas_address = vp->lvalue;
+                               ut.nas_address = vp->lvalue;
+                               break;
+                       case PW_NAS_PORT_ID:
+                               ut.nas_port = vp->lvalue;
+                               port_seen = 1;
+                               break;
+                       case PW_ACCT_DELAY_TIME:
+                               ut.delay = vp->lvalue;
+                               break;
+                       case PW_ACCT_SESSION_ID:
+                               /*
+                                *      If length > 8, only store the
+                                *      last 8 bytes.
+                                */
+                               off = vp->length - sizeof(ut.session_id);
+                               if (off < 0) off = 0;
+                               memcpy(ut.session_id, vp->strvalue + off,
+                                       sizeof(ut.session_id));
+                               break;
+                       case PW_NAS_PORT_TYPE:
+                               if (vp->lvalue >= 0 && vp->lvalue <= 4)
+                                       ut.porttype = porttypes[vp->lvalue];
+                               nas_port_type = vp->lvalue;
+                               break;
+                       case PW_CALLING_STATION_ID:
+                               strncpy(ut.caller_id, vp->strvalue,
+                                       sizeof(ut.caller_id));
+                               ut.caller_id[sizeof(ut.caller_id)] = 0;
+                               break;
+               }
+       }
+
+       /*
+        *      If we didn't find out the NAS address, use the
+        *      originator's IP address.
+        */
+       if (nas_address == 0) {
+               nas_address = request->packet->src_ipaddr;
+               ut.nas_address = nas_address;
+       }
+
+       if (protocol == PW_PPP)
+               ut.proto = 'P';
+       else if (protocol == PW_SLIP)
+               ut.proto = 'S';
+       else
+               ut.proto = 'T';
+       ut.time = t - ut.delay;
+
+       /*
+        *      See if this was a portmaster reboot.
+        */
+       if (status == PW_STATUS_ACCOUNTING_ON && nas_address) {
+               log(L_INFO, "NAS %s restarted (Accounting-On packet seen)",
+                       nas_name(nas_address));
+               radutmp_zap(nas_address, -1, NULL, ut.time);
+               return 0;
+       }
+       if (status == PW_STATUS_ACCOUNTING_OFF && nas_address) {
+               log(L_INFO, "NAS %s rebooted (Accounting-Off packet seen)",
+                       nas_name(nas_address));
+               radutmp_zap(nas_address, -1, NULL, ut.time);
+               return 0;
+       }
+
+       /*
+        *      If we don't know this type of entry pretend we succeeded.
+        */
+       if (status != PW_STATUS_START &&
+           status != PW_STATUS_STOP &&
+           status != PW_STATUS_ALIVE) {
+               log(L_ERR, "NAS %s port %d unknown packet type %d)",
+                       nas_name(nas_address), ut.nas_port, status);
+               return 0;
+       }
+
+       /*
+        *      Perhaps we don't want to store this record into
+        *      radutmp. We skip records:
+        *
+        *      - without a NAS-Port-Id (telnet / tcp access)
+        *      - with the username "!root" (console admin login)
+        */
+       if (!port_seen || strncmp(ut.login, "!root", RUT_NAMESIZE) == 0)
+               return 0;
+
+       /*
+        *      Enter into the radutmp file.
+        */
+       if ((fd = open(RADUTMP, O_RDWR|O_CREAT, 0644)) >= 0) {
+               NAS_PORT *cache;
+               int r;
+
+               /*
+                *      Lock the utmp file, prefer lockf() over flock().
+                */
+#if defined(F_LOCK) && !defined(BSD)
+               (void)lockf(fd, F_LOCK, LOCK_LEN);
+#else
+               (void)flock(fd, LOCK_EX);
+#endif
+               /*
+                *      Find the entry for this NAS / portno combination.
+                */
+               if ((cache = nas_port_find(ut.nas_address, ut.nas_port)) != NULL)
+                       lseek(fd, (off_t)cache->offset, SEEK_SET);
+
+               r = 0;
+               off = 0;
+               while (read(fd, &u, sizeof(u)) == sizeof(u)) {
+                       off += sizeof(u);
+                       if (u.nas_address != ut.nas_address ||
+                           u.nas_port    != ut.nas_port)
+                               continue;
+
+                       if (status == PW_STATUS_STOP &&
+                           strncmp(ut.session_id, u.session_id, 
+                            sizeof(u.session_id)) != 0) {
+                               /*
+                                *      Don't complain if this is not a
+                                *      login record (some clients can
+                                *      send _only_ logout records).
+                                */
+                               if (u.type == P_LOGIN)
+                                       log(L_ERR,
+               "Accounting: logout: entry for NAS %s port %d has wrong ID",
+                                       nas_name(nas_address), u.nas_port);
+                               r = -1;
+                               break;
+                       }
+
+                       if (status == PW_STATUS_START &&
+                           strncmp(ut.session_id, u.session_id, 
+                            sizeof(u.session_id)) == 0  &&
+                           u.time >= ut.time) {
+                               if (u.type == P_LOGIN) {
+                                       log(L_INFO,
+               "Accounting: login: entry for NAS %s port %d duplicate",
+                                       nas_name(nas_address), u.nas_port);
+                                       r = -1;
+                                       break;
+                               }
+                               log(L_ERR,
+               "Accounting: login: entry for NAS %s port %d wrong order",
+                               nas_name(nas_address), u.nas_port);
+                               r = -1;
+                               break;
+                       }
+
+                       /*
+                        *      FIXME: the ALIVE record could need
+                        *      some more checking, but anyway I'd
+                        *      rather rewrite this mess -- miquels.
+                        */
+                       if (status == PW_STATUS_ALIVE &&
+                           strncmp(ut.session_id, u.session_id, 
+                            sizeof(u.session_id)) == 0  &&
+                           u.type == P_LOGIN) {
+                               /*
+                                *      Keep the original login time.
+                                */
+                               ut.time = u.time;
+                               if (u.login[0] != 0)
+                                       just_an_update = 1;
+                       }
+
+                       if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
+                               log(L_ERR, "Accounting: negative lseek!\n");
+                               lseek(fd, (off_t)0, SEEK_SET);
+                               off = 0;
+                       } else
+                               off -= sizeof(u);
+                       r = 1;
+                       break;
+               }
+
+               if (r >= 0 &&  (status == PW_STATUS_START ||
+                               status == PW_STATUS_ALIVE)) {
+                       if (cache == NULL) {
+                          if ((cache = malloc(sizeof(NAS_PORT))) != NULL) {
+                                  cache->nasaddr = ut.nas_address;
+                                  cache->port = ut.nas_port;
+                                  cache->offset = off;
+                                  cache->next = nas_port_list;
+                                  nas_port_list = cache;
+                          }
+                       }
+                       ut.type = P_LOGIN;
+                       write(fd, &ut, sizeof(u));
+               }
+               if (status == PW_STATUS_STOP) {
+                       if (r > 0) {
+                               u.type = P_IDLE;
+                               u.time = ut.time;
+                               u.delay = ut.delay;
+                               write(fd, &u, sizeof(u));
+                       } else if (r == 0) {
+                               log(L_ERR,
+               "Accounting: logout: login entry for NAS %s port %d not found",
+                               nas_name(nas_address), ut.nas_port);
+                               r = -1;
+                       }
+               }
+               close(fd);
+       } else {
+               log(L_ERR, "Accounting: %s: %s", RADUTMP, strerror(errno));
+               ret = -1;
+       }
+
+       return ret;
+}
+
+
+/*
+ *     Timeout handler (10 secs)
+ */
+static int got_alrm;
+static void alrm_handler()
+{
+       got_alrm = 1;
+}
+
+/*
+ *     Check one terminal server to see if a user is logged in.
+ */
+static int rad_check_ts(struct radutmp *ut)
+{
+       int     pid, st, e;
+       int     n;
+       NAS     *nas;
+       char    address[16];
+       char    port[8];
+       char    session_id[12];
+       void    (*handler)(int);
+
+       /*
+        *      Find NAS type.
+        */
+       if ((nas = nas_find(ut->nas_address)) == NULL) {
+               log(L_ERR, "Accounting: unknown NAS");
+               return -1;
+       }
+
+       /*
+        *      Fork.
+        */
+       handler = signal(SIGCHLD, SIG_DFL);
+       if ((pid = fork()) < 0) {
+               log(L_ERR, "Accounting: fork: %s", strerror(errno));
+               signal(SIGCHLD, handler);
+               return -1;
+       }
+
+       if (pid > 0) {
+               /*
+                *      Parent - Wait for checkrad to terminate.
+                *      We timeout in 10 seconds.
+                */
+               got_alrm = 0;
+               signal(SIGALRM, alrm_handler);
+               alarm(10);
+               while((e = waitpid(pid, &st, 0)) != pid)
+                       if (e < 0 && (errno != EINTR || got_alrm))
+                               break;
+               alarm(0);
+               signal(SIGCHLD, handler);
+               if (got_alrm) {
+                       kill(pid, SIGTERM);
+                       sleep(1);
+                       kill(pid, SIGKILL);
+                       log(L_ERR, "Check-TS: timeout waiting for checkrad");
+                       return 2;
+               }
+               if (e < 0) {
+                       log(L_ERR, "Check-TS: unknown error in waitpid()");
+                       return 2;
+               }
+               return WEXITSTATUS(st);
+       }
+
+       /*
+        *      Child - exec checklogin with the right parameters.
+        */
+       for (n = 32; n >= 3; n--)
+               close(n);
+
+       ip_ntoa(address, ut->nas_address);
+       sprintf(port, "%d", ut->nas_port);
+       sprintf(session_id, "%.8s", ut->session_id);
+
+       execl(CHECKRAD, "checkrad", nas->nastype, address, port,
+               ut->login, session_id, NULL);
+       log(L_ERR, "Check-TS: exec %s: %s", CHECKRAD, strerror(errno));
+
+       /*
+        *      Exit - 2 means "some error occured".
+        */
+       exit(2);
+}
+
+/*
+ *     See if a user is already logged in.
+ *
+ *     Check twice. If on the first pass the user exceeds his
+ *     max. number of logins, do a second pass and validate all
+ *     logins by querying the terminal server (using eg. SNMP).
+ *
+ *     Returns: 0 == OK, 1 == double logins, 2 == multilink attempt
+ */
+int radutmp_checksimul(char *name, VALUE_PAIR *request, int maxsimul)
+{
+       VALUE_PAIR      *fra;
+       struct radutmp  u;
+       UINT4           ipno = 0;
+       int             fd;
+       int             count;
+       int             mpp = 1;
+
+       if ((fd = open(RADUTMP, O_CREAT|O_RDWR, 0644)) < 0)
+               return 0;
+
+       /*
+        *      We don't lock in the first pass.
+        */
+       count = 0;
+       while(read(fd, &u, sizeof(u)) == sizeof(u))
+               if (strncmp(name, u.login, RUT_NAMESIZE) == 0
+                   && u.type == P_LOGIN)
+                       count++;
+
+       if (count < maxsimul) {
+               close(fd);
+               return 0;
+       }
+       lseek(fd, (off_t)0, SEEK_SET);
+
+       /*
+        *      Setup some stuff, like for MPP detection.
+        */
+       if ((fra = pairfind(request, PW_FRAMED_IP_ADDRESS)) != NULL)
+               ipno = fra->lvalue;
+
+       /*
+        *      lockf() the file while reading/writing.
+        */
+#if defined(F_LOCK) && !defined(BSD)
+               (void)lockf(fd, F_LOCK, LOCK_LEN);
+#else
+               (void)flock(fd, LOCK_EX);
+#endif
+
+       /*
+        *      Allright, there are too many concurrent logins.
+        *      Check all registered logins by querying the
+        *      terminal server directly.
+        *      FIXME: rad_check_ts() runs with locked radwtmp file!
+        */
+       count = 0;
+       while (read(fd, &u, sizeof(u)) == sizeof(u)) {
+               if (strncmp(name, u.login, RUT_NAMESIZE) == 0
+                   && u.type == P_LOGIN) {
+                       if (rad_check_ts(&u) == 1) {
+                               count++;
+                               /*
+                                *      Does it look like a MPP attempt?
+                                */
+                               if (strchr("SCPA", u.proto) &&
+                                   ipno && u.framed_address == ipno)
+                                       mpp = 2;
+                       }
+                       else {
+                               /*
+                                *      False record - zap it.
+                                */
+
+                               lseek(fd, -(off_t)sizeof(u), SEEK_CUR);
+                               u.type = P_IDLE;
+                               write(fd, &u, sizeof(u));
+
+#if 0 /* FIXME: should we fixup radwtmp as well or not ? */
+                               if ((wfp = fopen(RADWTMP, "a")) != NULL) {
+                                       make_wtmp(&u, &wt, PW_STATUS_STOP);
+                                       fwrite(&wt, sizeof(wt), 1, wfp);
+                                       fclose(wfp);
+                               }
+#endif
+                       }
+               }
+       }
+       close(fd);
+
+       return (count < maxsimul) ? 0 : mpp;
+}
+
diff --git a/src/main/radwho.c b/src/main/radwho.c
new file mode 100644 (file)
index 0000000..de92d01
--- /dev/null
@@ -0,0 +1,553 @@
+/*
+ * radwho      Show who is logged in on the terminal servers.
+ *             Can also be installed as fingerd on the UNIX
+ *             machine RADIUS runs on.
+ *
+ * Version:    @(#)radwho  1.25  27-Apr-1999  miquels@cistron.nl
+ *
+ * Patch:      22-Apr-1999     promera@cistron.nl
+ *             Added support for raw, comma seperated output
+ */
+
+#include "autoconf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <time.h>
+#include <ctype.h>
+#include <netinet/in.h>
+
+#if HAVE_MALLOC_H
+#  include <malloc.h>
+#endif
+
+#include "sysutmp.h"
+#include "radutmp.h"
+#include "radiusd.h"
+
+/*
+ *     FIXME: put in header file.
+ */
+#define SYS_FINGER "/usr/bin/finger"
+#define FINGER_DIR "/usr/local/lib/finger"
+
+/*
+ *     Header above output and format.
+ */
+char *hdr1 = 
+"Login      Name              What  TTY  When      From      Location";
+char *ufmt1 = "%-10.10s %-17.17s %-5.5s %-4.4s %-9.9s %-9.9s %-.16s%s";
+char *ufmt1r = "%s,%s,%s,%s,%s,%s,%s%s";
+char *rfmt1 = "%-10.10s %-17.17s %-5.5s S%-3d %-9.9s %-9.9s %-.19s%s";
+char *rfmt1r = "%s,%s,%s,S%d,%s,%s,%s%s";
+
+char *hdr2 = 
+"Login      Port    What      When          From       Location";
+char *ufmt2 = "%-10.10s %-7.7d %-9.9s %-13.13s %-10.10s %-.16s%s";
+char *ufmt2r = "%s,%d,%s,%s,%s,%s%s";
+char *rfmt2 = "%-10.10s S%-5d  %-9.9s %-13.13s %-10.10s %-.28s%s";
+char *rfmt2r = "%s,S%d,%s,%s,%s,%s%s";
+
+char *eol = "\n";
+NAS *naslist;
+int showname = -1;
+int showptype = 0;
+int showcid = 0;
+
+/*
+ *     Safe popen. Ugh.
+ */
+FILE *safe_popen(char *cmd, char *mode)
+{
+       char            *p;
+       char            buf[1024];
+
+       /*
+        *      Change all suspect characters into a space.
+        */
+       strncpy(buf, cmd, sizeof(buf));
+       buf[sizeof(buf) - 1] = 0;
+       for (p = buf; *p; p++) {
+               if (isalnum(*p))
+                       continue;
+               if (strchr("@%-_ \t+:,./", *p) == NULL)
+                       *p = ' ';
+       }
+
+       return popen(buf, mode);
+}
+
+/*
+ *     Read the naslist file.
+ */
+static NAS *my_read_naslist_file(char *file)
+{
+       FILE    *fp;
+       char    buffer[256];
+       char    hostnm[128];
+       char    shortnm[32];
+       char    nastype[32];
+       int     lineno = 0;
+       NAS     *cl = NULL;
+       NAS     *c;
+
+       if ((fp = fopen(file, "r")) == NULL) {
+               fprintf(stderr, "cannot open %s\n", file);
+               return NULL;
+       }
+       while(fgets(buffer, 256, fp) != NULL) {
+               lineno++;
+               if (buffer[0] == '#' || buffer[0] == '\n')
+                       continue;
+               shortnm[0] = 0;
+               if (sscanf(buffer, "%s%s%s", hostnm, shortnm, nastype) < 2) {
+                       fprintf(stderr, "%s[%d]: syntax error\n", file, lineno);
+                       continue;
+               }
+               if ((c = malloc(sizeof(NAS))) == NULL) {
+                       fprintf(stderr, "%s[%d]: out of memory\n",
+                               file, lineno);
+                       return NULL;
+               }
+
+               c->ipaddr = ip_getaddr(hostnm);
+               strcpy(c->nastype, nastype);
+               strcpy(c->shortname, shortnm);
+               strcpy(c->longname, ip_hostname(c->ipaddr));
+
+               c->next = cl;
+               cl = c;
+       }
+       fclose(fp);
+
+       return cl;
+}
+
+
+/*
+ *     Print a file from FINGER_DIR. If the file is executable,
+ *     execute it instead. Return 0 if succesfull.
+ */
+int ffile(char *arg)
+{
+       FILE *fp;
+       char fn[1024];
+       int p = 0;
+       char *s;
+
+       sprintf(fn, "%s/%.32s", FINGER_DIR, arg);
+       if (access(fn, X_OK) == 0) {
+               p = 1;
+               sprintf(fn, "exec %s/%.32s 2>&1", FINGER_DIR, arg);
+               fp = safe_popen(fn, "r");
+       } else fp = fopen(fn, "r");
+
+       if (fp == NULL) return -1;
+
+       while(fgets(fn, 1024, fp)) {
+               if ((s = strchr(fn, '\n')) != NULL)
+                       *s = 0;
+               fprintf(stdout, "%s\r\n", fn);
+       }
+       if (p)
+               pclose(fp);
+       else
+               fclose(fp);
+       fflush(stdout);
+       return 0;
+}
+
+
+/*
+ *     Execute the system finger and translate LF to CRLF.
+ */
+void sys_finger(char *l)
+{
+       FILE *fp;
+       char fn[1024];
+       char *p;
+
+       if (ffile(l) == 0)
+               exit(0);
+
+       sprintf(fn, "exec %s %s", SYS_FINGER, l);
+       if ((fp = safe_popen(fn, "r")) == NULL) {
+               printf("popen: %s\r\n", strerror(errno));
+               exit(1);
+       }
+
+       while(fgets(fn, 1024, fp)) {
+               if ((p = strchr(fn, '\n')) != NULL)
+                       *p = 0;
+               fprintf(stdout, "%s\r\n", fn);
+       }
+       pclose(fp);
+       exit(0);
+}
+
+
+/*
+ *     Get fullname of a user.
+ */
+char *fullname(char *login)
+{
+       struct passwd *pwd;
+       char *s;
+
+       if ((pwd = getpwnam(login)) != NULL) {
+               if ((s = strchr(pwd->pw_gecos, ',')) != NULL) *s = 0;
+               return pwd->pw_gecos;
+       }
+       return login;
+}
+
+/*
+ *     Return protocol type.
+ */
+char *proto(int id, int porttype)
+{
+       static char buf[8];
+
+       if (showptype) {
+               if (!strchr("ASITX", porttype))
+                       porttype = ' ';
+               if (id == 'S')
+                       sprintf(buf, "SLP %c", porttype);
+               else if (id == 'P')
+                       sprintf(buf, "PPP %c", porttype);
+               else
+                       sprintf(buf, "shl %c", porttype);
+               return buf;
+       }
+       if (id == 'S') return "SLIP";
+       if (id == 'P') return "PPP";
+       return "shell";
+}
+
+/*
+ *     Return a time in the form day hh:mm
+ */
+char *dotime(time_t t)
+{
+       char *s = ctime(&t);
+
+       if (showname) {
+               strncpy(s + 4, s + 11, 5);
+               s[9] = 0;
+       } else {
+               strncpy(s + 4, s + 8, 8);
+               s[12] = 0;
+       }
+
+       return s;
+}
+
+#if 0 /*UNUSED*/
+/*
+ *     See how long a tty has been idle.
+ */
+char *idletime(char *line)
+{
+       char tty[16];
+       static char tmp[8];
+       time_t t;
+       struct stat st;
+       int hr, min, days;
+
+       if (line[0] == '/')
+               strcpy(tty, "/dev/");
+       else
+               tty[0] = 0;
+       strcat(tty, line);
+
+       tmp[0] = 0;
+       if (stat(tty, &st) == 0) {
+               time(&t);
+               t -= st.st_mtime;
+               if (t >= 60) {
+                       min = (t / 60);
+                       hr = min / 24;
+                       days = hr / 24;
+                       min %= 60;
+                       hr %= 24;
+                       if (days > 0)
+                               sprintf(tmp, "%dd", days);
+                       else
+                               sprintf(tmp, "%2d:%02d", hr, min);
+               }
+       }
+       return tmp;
+}
+#endif
+
+/*
+ *     Shorten tty name.
+ */
+char *ttyshort(char *tty)
+{
+       static char tmp[16];
+
+       if (tty[0] == '/') tty += 5;
+
+       if (strncmp(tty, "tty", 3) == 0) {
+               if (tty[3] >= '0' && tty[3] <= '9')
+                       sprintf(tmp, "v%s", tty + 3);
+               else
+                       sprintf(tmp, "%s", tty + 3);
+               return tmp;
+       }
+       if (strncmp(tty, "vc", 2) == 0) {
+               sprintf(tmp, "v%s", tty + 2);
+               return tmp;
+       }
+       if (strncmp(tty, "cu", 2) == 0) {
+               return tmp + 2;
+       }
+       return "??";
+}
+
+
+/*
+ *     Find name of NAS
+ */
+char *nasname(UINT4 ipaddr)
+{
+       NAS *cl;
+
+       for(cl = naslist; cl; cl = cl->next)
+               if (cl->ipaddr == ipaddr)
+                       break;
+       if (cl == NULL)
+               return "";
+       if (cl->shortname[0])
+               return cl->shortname;
+       return cl->longname;
+}
+
+
+/*
+ *     Print address of NAS.
+ */
+char *hostname(UINT4 ipaddr)
+{
+       if (ipaddr == 0 || ipaddr == (UINT4)-1 || ipaddr == (UINT4)-2)
+               return "";
+       return ip_hostname(ipaddr);
+}
+
+
+/*
+ *     Print usage message and exit.
+ */
+void usage(void)
+{
+       fprintf(stderr, "Usage: radwho [-lhfnsipcr]\n");
+       fprintf(stderr, "       -l: show local (shell) users too\n");
+       fprintf(stderr, "       -h: hide shell users from radius\n");
+       fprintf(stderr, "       -f: give fingerd output\n");
+       fprintf(stderr, "       -n: no full name\n");
+       fprintf(stderr, "       -s: show full name\n");
+       fprintf(stderr, "       -i: show session ID\n");
+       fprintf(stderr, "       -p: show port type\n");
+       fprintf(stderr, "       -c: show caller ID, if available\n");
+       fprintf(stderr, "       -r: output as raw data\n");
+       exit(1);
+}
+
+
+/*
+ *     Main program, either pmwho or fingerd.
+ */
+int main(int argc, char **argv)
+{
+       FILE *fp;
+       struct radutmp rt;
+       struct utmp ut;
+       int hdrdone = 0;
+       char inbuf[128];
+       char myname[128];
+       char session_id[16];
+       int fingerd = 0;
+       int showlocal = 0;
+       int hideshell = 0;
+       int showsid = 0;
+       int rawoutput = 0;
+       char *p, *q;
+       int c;
+
+       while((c = getopt(argc, argv, "flhnsipcr")) != EOF) switch(c) {
+               case 'f':
+                       fingerd++;
+                       showname = 0;
+                       break;
+               case 'l':
+                       showlocal = 1;
+                       break;
+               case 'h':
+                       hideshell = 1;
+                       break;
+               case 'n':
+                       showname = 0;
+                       break;
+               case 's':
+                       showname = 1;
+                       break;
+               case 'i':
+                       showsid = 1;
+                       break;
+               case 'p':
+                       showptype = 1;
+                       break;
+               case 'c':
+                       showcid = 1;
+                       showname = 1;
+                       break;
+               case 'r':
+                       rawoutput = 1;
+                       break;
+               default:
+                       usage();
+                       break;
+       }
+
+       /*
+        *      Read the "naslist" file.
+        */
+       sprintf(inbuf, "%s/%s", RADIUS_DIR, RADIUS_NASLIST);
+       if ((naslist = my_read_naslist_file(inbuf)) == NULL)
+               exit(1);
+
+       /*
+        *      See if we are "fingerd".
+        */
+       if (strstr(argv[0], "fingerd")) {
+               fingerd++;
+               eol = "\r\n";
+               if (showname < 0) showname = 0;
+       }
+       if (showname < 0) showname = 1;
+
+       if (fingerd) {
+               /*
+                *      Read first line of the input.
+                */
+               fgets(inbuf, 128, stdin);
+               p = inbuf;
+               while(*p == ' ' || *p == '\t') p++;
+               if (*p == '/' && *(p + 1)) p += 2;
+               while(*p == ' ' || *p == '\t') p++;
+               for(q = p; *q && *q != '\r' && *q != '\n'; q++)
+                       ;
+               *q = 0;
+
+               /*
+                *      See if we fingered a specific user.
+                */
+               ffile("header");
+               if (*p) sys_finger(p);
+       }
+
+       if (showlocal && (fp = fopen(UTMP_FILE, "r"))) {
+               if (rawoutput == 0)
+               {       
+                       fputs(showname ? hdr1 : hdr2, stdout);
+                       fputs(eol, stdout);
+               }
+               hdrdone = 1;
+
+               /*
+                *      Show the logged in UNIX users.
+                */
+               gethostname(myname, 128);
+               while(fread(&ut, sizeof(ut), 1, fp) == 1) {
+#ifdef USER_PROCESS
+                       if (ut.ut_user[0] && ut.ut_line[0] &&
+                               ut.ut_type == USER_PROCESS) {
+#else
+                       if (ut.ut_user[0] && ut.ut_line[0]) {
+#endif
+                          if (showname)
+                               printf((rawoutput == 0? ufmt1: ufmt1r),
+                                       ut.ut_name,
+                                       fullname(ut.ut_name),
+                                       "shell",
+                                       ttyshort(ut.ut_line),
+#ifdef __svr4__
+                                       dotime(ut.ut_xtime),
+#else
+                                       dotime(ut.ut_time),
+#endif
+                                       ut.ut_host,
+                                       myname, eol);
+                           else
+                               printf((rawoutput==0? ufmt2:ufmt2r),
+                                       ut.ut_name,
+                                       ttyshort(ut.ut_line),
+                                       "shell",
+#ifdef __svr4__
+                                       dotime(ut.ut_xtime),
+#else
+                                       dotime(ut.ut_time),
+#endif
+                                       ut.ut_host,
+                                       myname, eol);
+                       }
+               }
+               fclose(fp);
+       }
+
+       /*
+        *      Show the users logged in on the terminal server(s).
+        */
+       if ((fp = fopen(RADUTMP, "r")) == NULL)
+               return 0;
+
+       if (!hdrdone) {
+               fputs(showname ? hdr1 : hdr2, stdout);
+               fputs(eol, stdout);
+       }
+
+       while(fread(&rt, sizeof(rt), 1, fp) == 1) {
+               if (rt.type == P_LOGIN) {
+                       /*
+                        *      We don't show shell users if we are
+                        *      fingerd, as we have done that above.
+                        */
+                       if (hideshell && !strchr("PCS", rt.proto))
+                               continue;
+
+                       sprintf(session_id, "%.8s", rt.session_id);
+
+                       if (showname)
+                           printf((rawoutput == 0? rfmt1: rfmt1r),
+                               rt.login,
+                               showcid ? rt.caller_id :
+                               (showsid? session_id : fullname(rt.login)),
+                               proto(rt.proto, rt.porttype),
+                               rt.nas_port,
+                               dotime(rt.time),
+                               nasname(rt.nas_address),
+                               hostname(rt.framed_address), eol);
+                       else
+                           printf((rawoutput == 0? rfmt2: rfmt2r),
+                               rt.login,
+                               rt.nas_port,
+                               proto(rt.proto, rt.porttype),
+                               dotime(rt.time),
+                               nasname(rt.nas_address),
+                               hostname(rt.framed_address), eol);
+               }
+       }
+       fflush(stdout);
+       fflush(stderr);
+       fclose(fp);
+
+       return 0;
+}
+
diff --git a/src/main/radzap.c b/src/main/radzap.c
new file mode 100644 (file)
index 0000000..b5420c9
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * radzap      Zap a user from the radutmp and radwtmp file.
+ *
+ * Version:    @(#)radzap  2.13  08-Aug-1999  miquels@cistron.nl
+ *
+ */
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+#include       <sys/file.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <fcntl.h>
+#include       <time.h>
+#include       <unistd.h>
+#include       <errno.h>
+#include       <stdarg.h>
+#include       <netinet/in.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+
+int debug_flag = 0;
+char *progname = "radzap";
+char *radlog_dir = NULL;
+
+/*
+ *     Zap a user from the radutmp and radwtmp file.
+ */
+int main(int argc, char **argv)
+{
+       NAS     *nas;
+       UINT4   ip = 0;
+       int     nas_port = -1;
+       char    *user = NULL;
+       char    *s;
+       time_t  t;
+       char    buf[256];
+
+       if (argc < 2 || argc > 4 || (argc > 1 && argv[1][0] == '-')) {
+               fprintf(stderr, "Usage: radzap termserver [port] [user]\n");
+               fprintf(stderr, "       radzap is only an admin tool to clean the radutmp file!\n");
+               exit(1);
+       }
+       if (argc > 2) {
+               s = argv[2];
+               if (*s == 's' || *s == 'S') s++;
+               nas_port = atoi(s);
+       }
+       if (argc > 3) user     = argv[3];
+
+       /*
+        *      Read the "naslist" file.
+        */
+       sprintf(buf, "%s/%s", RADIUS_DIR, RADIUS_NASLIST);
+       if (read_naslist_file(buf) < 0)
+               exit(1);
+
+       /*
+        *      Find the IP address of the terminal server.
+        */
+       if ((nas = nas_findbyname(argv[1])) == NULL && argv[1][0] != 0) {
+               if ((ip = ip_getaddr(argv[1])) == 0) {
+                       fprintf(stderr, "%s: host not found.\n", argv[1]);
+                       exit(1);
+               }
+       }
+       if (nas) ip = nas->ipaddr;
+
+       printf("radzap: zapping termserver %s, port %d",
+               ip_hostname(ip), nas_port);
+       if (user) printf(", user %s", user);
+       printf("\n");
+
+       t = time(NULL);
+       radutmp_zap(ip, nas_port, user, t);
+
+       return 0;
+}
diff --git a/src/main/timestr.c b/src/main/timestr.c
new file mode 100644 (file)
index 0000000..18f8315
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+ * timestr.c   See if a string like 'Su2300-0700' matches (UUCP style).
+ *
+ * Version:    @(#)timestr.c  0.10  21-Mar-1999 miquels@cistron.nl
+ *
+ */
+
+#include       "autoconf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <ctype.h>
+
+static char *days[] =
+       { "su", "mo", "tu", "we", "th", "fr", "sa", "wk", "any", "al" };
+
+#define DAYMIN         (24*60)
+#define WEEKMIN                (24*60*7)
+#define val(x)         (( (x) < 48 || (x) > 57) ? 0 : ((x) - 48))
+
+#ifdef DEBUG
+#  define xprintf if (1) printf
+#else
+#  define xprintf if (0) printf
+#endif
+
+/*
+ *     String code.
+ */
+static int strcode (char **str)
+{
+       int             i, l;
+
+       xprintf("strcode %s called\n", *str);
+
+       for (i = 0; i < 10; i++) {
+               l = strlen(days[i]);
+               if (l > strlen(*str))
+                       continue;
+               if (strncmp(*str, days[i], l) == 0) {
+                       *str += l;
+                       break;
+               }
+       }
+       xprintf("strcode result %d\n", i);
+
+       return (i >= 10) ? -1 : i;
+
+}
+
+/*
+ *     Fill bitmap with hours/mins.
+ */
+static int hour_fill(char *bitmap, char *tm)
+{
+       char            *p;
+       int             start, end;
+       int             i, bit, byte;
+
+       xprintf("hour_fill called for %s\n", tm);
+
+       /*
+        *      Get timerange in start and end.
+        */
+       end = -1;
+       if ((p = strchr(tm, '-')) != NULL) {
+               p++;
+               if (p - tm != 5 || strlen(p) < 4 || !isdigit(*p))
+                       return 0;
+               end = 600 * val(p[0]) + 60 * val(p[1]) + atoi(p + 2);
+       }
+       if (*tm == 0) {
+               start = 0;
+               end = DAYMIN - 1;
+       } else {
+               if (strlen(tm) < 4 || !isdigit(*tm))
+                       return 0;
+               start = 600 * val(tm[0]) + 60 * val(tm[1]) + atoi(tm + 2);
+               if (end < 0) end = start;
+       }
+       /* Treat 2400 as 0000, and do some more silent error checks. */
+       if (end < 0)   end = 0;
+       if (start < 0) start = 0;
+       if (end >= DAYMIN)   end = DAYMIN - 1;
+       if (start >= DAYMIN) start = DAYMIN - 1;
+
+       xprintf("hour_fill: range from %d to %d\n", start, end);
+
+       /*
+        *      Fill bitmap.
+        */
+       i = start;
+       while (1) {
+               byte = (i / 8);
+               bit  = i % 8;
+               xprintf("setting byte %d, bit %d\n", byte, bit);
+               bitmap[byte] |= (1 << bit);
+               if (i == end) break;
+               i++;
+               i %= DAYMIN;
+       }
+       return 1;
+}
+
+/*
+ *     Call the fill bitmap function for every day listed.
+ */
+static int day_fill(char *bitmap, char *tm)
+{
+       char            *hr;
+       int             n;
+       int             start, end;
+
+       for (hr = tm; *hr; hr++)
+               if (isdigit(*hr))
+                       break;
+       if (hr == tm) tm = "Al";
+
+       xprintf("dayfill: hr %s    tm %s\n", hr, tm);
+
+       while ((start = strcode(&tm)) >= 0) {
+               /*
+                *      Find start and end weekdays and
+                *      build a valid range 0 - 6.
+                */
+               if (*tm == '-') {
+                       tm++;
+                       if ((end = strcode(&tm)) < 0)
+                               break;
+               } else
+                       end = start;
+               if (start == 7) {
+                       start = 1;
+                       end = 5;
+               }
+               if (start > 7) {
+                       start = 0;
+                       end = 6;
+               }
+               n = start;
+               xprintf("day_fill: range from %d to %d\n", start, end);
+               while (1) {
+                       hour_fill(bitmap + 180 * n, hr);
+                       if (n == end) break;
+                       n++;
+                       n %= 7;
+               }
+       }
+
+       return 1;
+}
+
+/*
+ *     Fill the week bitmap with allowed times.
+ */
+static int week_fill(char *bitmap, char *tm)
+{
+       char            *s;
+       char            tmp[128];
+
+       strncpy(tmp, tm, 128);
+       tmp[127] = 0;
+       for (s = tmp; *s; s++)
+               if (isupper(*s)) *s = tolower(*s);
+
+       s = strtok(tmp, ",|");
+       while (s) {
+               day_fill(bitmap, s);
+               s = strtok(NULL, ",|");
+       }
+
+       return 0;
+}
+
+/*
+ *     Match a timestring and return seconds left.
+ *     -1 for no match, 0 for unlimited.
+ */
+int timestr_match(char *tmstr, time_t t)
+{
+       struct tm       *tm;
+       char            bitmap[WEEKMIN / 8];
+       int             now, tot, i;
+       int             byte, bit;
+#if DEBUG2
+       int             y;
+       char            *s;
+       char            null[8];
+#endif
+
+       tm = localtime(&t);
+       now = tm->tm_wday * DAYMIN + tm->tm_hour * 60 + tm->tm_min;
+       tot = 0;
+       memset(bitmap, 0, sizeof(bitmap));
+       week_fill(bitmap, tmstr);
+
+#if DEBUG2
+       memset(null, 0, 8);
+       for (i = 0; i < 7; i++) {
+               printf("%d: ", i);
+               s = bitmap + 180 * i;
+               for (y = 0; y < 23; y++) {
+                       s = bitmap + 180 * i + (75 * y) / 10;
+                       printf("%c", memcmp(s, null, 8) == 0 ? '.' : '#');
+               }
+               printf("\n");
+       }
+#endif
+
+       /*
+        *      See how many minutes we have.
+        */
+       i = now;
+       while (1) {
+               byte = i / 8;
+               bit = i % 8;
+               xprintf("READ: checking byte %d bit %d\n", byte, bit);
+               if (!(bitmap[byte] & (1 << bit)))
+                       break;
+               tot += 60;
+               i++;
+               i %= WEEKMIN;
+               if (i == now)
+                       break;
+       }
+
+       if (!tot) return -1;
+       return (i == now) ? 0 : tot;
+}
+
+#ifdef STANDALONE
+
+int main(int argc, char **argv)
+{
+       int             l;
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: test timestring\n");
+               exit(1);
+       }
+       l = timestr_match(argv[1], time(NULL));
+       printf ("%s: %d seconds left\n", argv[1], l);
+       return 0;
+}
+
+#endif
+
diff --git a/src/main/util.c b/src/main/util.c
new file mode 100644 (file)
index 0000000..02fce9a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * util.c      Various utility functions.
+ *
+ * Version:     @(#)util.c  2.20  17-Jul-1999  miquels@cistron.nl
+ */
+
+char util_sccsid[] =
+"@(#)util.c    2.20 Copyright 1997-1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+#include       <arpa/inet.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <netdb.h>
+#include       <pwd.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <signal.h>
+
+#include       "radiusd.h"
+
+/*
+ *     Call getpwnam but cache the result.
+ */
+struct passwd *rad_getpwnam(char *name)
+{
+       static struct passwd *lastpwd;
+       static char lastname[64];
+       static time_t lasttime = 0;
+       time_t now;
+
+       now = time(NULL);
+
+       if ((now <= lasttime + 5 ) && strncmp(name, lastname, 64) == 0)
+               return lastpwd;
+
+       strncpy(lastname, name, 63);
+       lastname[63] = 0;
+       lastpwd = getpwnam(name);
+       lasttime = now;
+
+       return lastpwd;
+}
+
+#if defined (sun) && defined(__svr4__)
+/*
+ *     The signal() function in Solaris 2.5.1 sets SA_NODEFER in
+ *     sa_flags, which causes grief if signal() is called in the
+ *     handler before the cause of the signal has been cleared.
+ *     (Infinite recursion).
+ */
+void (*sun_signal(int signo, void (*func)(int)))(int)
+{
+       struct sigaction act, oact;
+
+       act.sa_handler = func;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = 0;
+#ifdef  SA_INTERRUPT           /* SunOS */
+       act.sa_flags |= SA_INTERRUPT;
+#endif
+       if (sigaction(signo, &act, &oact) < 0)
+               return SIG_ERR;
+       return oact.sa_handler;
+}
+#endif
+
+
+/*
+ *     Free an AUTHREQ struct.
+ */
+void request_free(REQUEST *request)
+{
+       if (request->packet)
+               rad_free(request->packet);
+       if (request->proxy)
+               rad_free(request->proxy);
+       free(request);
+}
+
+
+/*
+ *     Build a reply radius packet, based on the request data.
+ */
+RADIUS_PACKET *build_reply(int code, REQUEST *request,
+       VALUE_PAIR *vps, char *user_msg)
+{
+       RADIUS_PACKET   *rp;
+       VALUE_PAIR      *vp;
+
+       if ((rp = rad_alloc(0)) == NULL) {
+               fprintf(stderr, "out of memory\n");
+               exit(1);
+       }
+       rp->dst_ipaddr = request->packet->src_ipaddr;
+       rp->dst_port   = request->packet->src_port;
+       rp->id         = request->packet->id;
+       rp->code       = code;
+       memcpy(rp->vector, request->packet->vector, sizeof(rp->vector));
+       rp->vps        = paircopy(vps);
+
+       /*
+        *      Need to copy PROXY_PAIRS from request->packet->vps
+        */
+       if ((vp = paircopy2(request->packet->vps, PW_PROXY_STATE)) != NULL)
+               pairadd(&(rp->vps), vp);
+
+       if (user_msg && !(vp = paircreate(PW_REPLY_MESSAGE, PW_TYPE_STRING))) {
+               strcpy(vp->strvalue, user_msg);
+               vp->length = strlen(user_msg);
+               pairadd(&(rp->vps), vp);
+       }
+
+       return rp;
+}
+
diff --git a/src/main/valuepair.c b/src/main/valuepair.c
new file mode 100644 (file)
index 0000000..cdf592a
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * valuepair.c Valuepair functions that are radiusd-specific
+ *             and as such do not belong in the library.
+ *
+ * Version:    @(#)valuepair.c  1.00  08-Aug-1999  miquels@cistron.nl
+ */
+
+char valuepair2_sccsid[] =
+"@(#)valuepair.c       1.00 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <time.h>
+#include       <netinet/in.h>
+
+#ifdef HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+
+struct cmp {
+       int             attribute;
+       int             otherattr;
+       COMPARE         compare;
+       struct cmp      *next;
+};
+static struct cmp *cmp;
+
+
+/*
+ *     Compare 2 attributes. May call the attribute compare function.
+ */
+int paircompare(VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       int             ret = -2;
+       struct cmp      *c;
+
+       /*
+        *      Sanity check.
+        */
+#if 0
+       if (request->attribute != check->attribute)
+               return -2;
+#endif
+
+       /*
+        *      See if there is a special compare function.
+        */
+       for (c = cmp; c; c = c->next)
+               if (c->attribute == check->attribute)
+                       return (c->compare)(request, check,
+                               check_pairs, reply_pairs);
+
+       switch(check->type) {
+               case PW_TYPE_STRING:
+                       ret = strcmp(request->strvalue, check->strvalue);
+                       break;
+               case PW_TYPE_INTEGER:
+               case PW_TYPE_DATE:
+                       ret = request->lvalue - check->lvalue;
+                       break;
+               case PW_TYPE_IPADDR:
+                        ret = ntohl(request->lvalue) -
+                              ntohl(check->lvalue);
+                       break;
+               default:
+                       break;
+       }
+
+       return ret;
+}
+
+
+/*
+ *     See what attribute we want to compare with.
+ */
+static int otherattr(int attr)
+{
+       struct cmp      *c;
+
+       for (c = cmp; c; c = c->next) {
+               if (c->attribute == attr)
+                       return c->otherattr;
+       }
+
+       return attr;
+}
+
+/*
+ *     Register a function as compare function.
+ *     Otherattr is the attribute in the request we want to
+ *     compare with. Normally this is the same as "attr".
+ *     You can set this to:
+ *
+ *     -1   the same as "attr"
+ *     0    always call compare function, not tied to request attribute
+ *     >0   Attribute to compare with.
+ *
+ *     For example, PW_GROUP in a check item needs to be compared
+ *     with PW_USER_NAME in the incoming request.
+ */
+int paircompare_register(int attr, int otherattr, COMPARE fun)
+{
+       struct cmp      *c;
+
+       paircompare_unregister(attr, fun);
+
+       if ((c = malloc(sizeof(struct cmp))) == NULL)
+               return -1;
+       if (otherattr < 0) otherattr = attr;
+       c->compare = fun;
+       c->attribute = attr;
+       c->otherattr = otherattr;
+       c->next = cmp;
+       cmp = c;
+
+       return 0;
+}
+
+/*
+ *     Unregister a function.
+ */
+void paircompare_unregister(int attr, COMPARE fun)
+{
+       struct cmp      *c, *last;
+
+       last = NULL;
+       for (c = cmp; c; c = c->next) {
+               if (c->attribute == attr && c->compare == fun)
+                       break;
+               last = c;
+       }
+
+       if (c == NULL) return;
+
+       if (last)
+               last->next = c->next;
+       else
+               cmp = c->next;
+
+       free(c);
+}
+
+/*
+ *     Compare two pair lists except for the password information.
+ *     For every element in "check" at least one matching copy must
+ *     be present in "reply".
+ *
+ *     Return 0 on match.
+ */
+int paircmp(VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **reply)
+{
+       VALUE_PAIR      *check_item = check;
+       VALUE_PAIR      *auth_item;
+       int             result = 0;
+       int             compare;
+       int             other;
+
+       while (result == 0 && check_item != NULL) {
+               switch (check_item->attribute) {
+                       /*
+                        *      Attributes we skip during comparison.
+                        *      These are "server" check items.
+                        */
+                       case PW_EXPIRATION:
+                       case PW_LOGIN_TIME:
+                       case PW_PASSWORD:
+                       case PW_CRYPT_PASSWORD:
+                       case PW_AUTHTYPE:
+                        case PAM_AUTH_ATTR:
+                       case PW_SIMULTANEOUS_USE:
+                       case PW_STRIP_USERNAME:
+                               check_item = check_item->next;
+                               continue;
+               }
+               /*
+                *      See if this item is present in the request.
+                */
+               other = otherattr(check_item->attribute);
+               auth_item = request;
+               for (; auth_item != NULL; auth_item = auth_item->next) {
+                       if (auth_item->attribute == other || other == 0)
+                               break;
+               }
+
+               if (auth_item == NULL) {
+                       result = -1;
+                       continue;
+               }
+
+               /*
+                *      OK it is present now compare them.
+                */
+               
+               compare = paircompare(auth_item, check_item, check, reply);
+
+               switch (check_item->operator)
+                 {
+                 default:
+                   log(L_ERR,  "Invalid operator for item %s: "
+                               "reverting to '='", check_item->name);
+                   /*FALLTHRU*/
+                 case T_OP_EQ:
+                   if (compare != 0) return -1;
+                   break;
+
+                 case T_OP_NE:
+                   if (compare == 0) return -1;
+                   break;
+
+                 case T_OP_LT:
+                   if (compare >= 0) return -1;
+                   break;
+
+                 case T_OP_GT:
+                   if (compare <= 0) return -1;
+                   break;
+                   
+                 case T_OP_LE:
+                   if (compare > 0) return -1;
+                   break;
+
+                 case T_OP_GE:
+                   if (compare < 0) return -1;
+                   break;
+                 }
+
+               if (result == 0)
+                       check_item = check_item->next;
+       }
+
+       return result;
+}
+
+
+/*
+ *     Compare a Connect-Info and a Connect-Rate
+ */
+static int connectcmp(VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       int     rate;
+
+       rate = atoi(request->strvalue);
+       return rate - check->lvalue;
+}
+
+
+/*
+ *     Compare a portno with a range.
+ */
+static int portcmp(VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       char            buf[MAX_STRING_LEN];
+       char            *s, *p;
+       int             lo, hi;
+       int             port = request->lvalue;
+
+       strcpy(buf, check->strvalue);
+       s = strtok(buf, ",");
+
+       while (s) {
+               if ((p = strchr(s, '-')) != NULL)
+                       p++;
+               else
+                       p = s;
+               lo = atoi(s);
+               hi = atoi(p);
+               if (lo <= port && port <= hi) {
+                       return 0;
+               }
+               s = strtok(NULL, ",");
+       }
+
+       return -1;
+}
+
+/*
+ *     Compare prefix/suffix.
+ *
+ *     If they compare: 
+ *     - if PW_STRIP_USERNAME is present in check_pairs,
+ *       strip the username of prefix/suffix.
+ *     - if PW_STRIP_USERNAME is not present in check_pairs,
+ *       add a PW_STRIPPED_USERNAME to the request.
+ */
+static int presufcmp(VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       VALUE_PAIR      *vp;
+       char            *name = request->strvalue;
+       char            rest[MAX_STRING_LEN];
+       int             len, namelen;
+       int             ret = -1;
+
+#if 0 /* DEBUG */
+       printf("Comparing %s and %s, check->attr is %d\n",
+               name, check->strvalue, check->attribute);
+#endif
+
+       len = strlen(check->strvalue);
+       switch (check->attribute) {
+               case PW_PREFIX:
+                       ret = strncmp(name, check->strvalue, len);
+                       if (ret == 0 && rest)
+                               strcpy(rest, name + len);
+                       break;
+               case PW_SUFFIX:
+                       namelen = strlen(name);
+                       if (namelen < len)
+                               break;
+                       ret = strcmp(name + namelen - len, check->strvalue);
+                       if (ret == 0 && rest) {
+                               strncpy(rest, name, namelen - len);
+                               rest[namelen - len] = 0;
+                       }
+                       break;
+       }
+       if (ret != 0)
+               return ret;
+
+       if (pairfind(check_pairs, PW_STRIP_USERNAME)) {
+               strcpy(request->strvalue, rest);
+               request->length = strlen(rest);
+       } else {
+               if ((vp = pairfind(check_pairs, PW_STRIPPED_USERNAME)) != NULL){
+                       strcpy(vp->strvalue, rest);
+                       request->length = strlen(rest);
+               } else if ((vp = paircreate(PW_STRIPPED_USERNAME,
+                           PW_TYPE_STRING)) != NULL) {
+                       strcpy(vp->strvalue, rest);
+                       request->length = strlen(rest);
+                       pairadd(&request, vp);
+               }
+       }
+
+       return ret;
+}
+
+/*
+ *     Register server-builtin special attributes.
+ */
+void pair_builtincompare_init(void)
+{
+       paircompare_register(PW_NAS_PORT_ID, -1, portcmp);
+       paircompare_register(PW_PREFIX, PW_USER_NAME, presufcmp);
+       paircompare_register(PW_SUFFIX, PW_USER_NAME, presufcmp);
+       paircompare_register(PW_CONNECT_RATE, PW_CONNECT_INFO, connectcmp);
+}
+
diff --git a/src/main/version.c b/src/main/version.c
new file mode 100644 (file)
index 0000000..15ea19a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * version.c   Print version number and exit.
+ *
+ * Version:    @(#)version.c  1.30  19-Jul-1999  miquels@cistron.nl
+ *
+ */
+char version_sccsid[] =
+"@(#)version.c 1.30  Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include        <sys/types.h>
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       "radiusd.h"
+
+/*
+ *     Version number. This should ideally be created by autoconf
+ *     or similar, so that this would always be up to date.
+ */
+#define                VERSION         "cistron-1.6-alpha2 08-Aug-1999"
+
+/*
+ *     Display the revision number for this program
+ */
+void version(void)
+{
+
+       fprintf(stderr, "%s: RADIUS version %s\n", progname, VERSION);
+       fprintf(stderr, "Compilation flags: ");
+
+       /* here are all the conditional feature flags */
+#if defined(WITH_DBM)
+       fprintf(stderr," WITH_DBM");
+#endif
+#if defined(WITH_NDBM)
+       fprintf(stderr," WITH_NDBM");
+#endif
+#if defined(OSFC2)
+       fprintf(stderr," OSFC2");
+#endif
+#if defined(WITH_NTDOMAIN_HACK)
+       fprintf(stderr," WITH_NTDOMAIN_HACK");
+#endif
+#if defined(WITH_SPECIALIX_JETSTREAM_HACK)
+       fprintf(stderr," WITH_SPECIALIX_JETSTREAM_HACK");
+#endif
+#if defined(WITH_ASCEND_HACK)
+       fprintf(stderr," WITH_ASCEND_HACK");
+#endif
+#if defined(WITH_DICT_NOCASE)
+       fprintf(stderr," WITH_DICT_NOCASE");
+#endif
+#if defined(ATTRIB_NMC)
+       fprintf(stderr, " ATTRIB_NMC");
+#endif
+       fprintf(stderr,"\n");
+       exit (0);
+}
+
diff --git a/src/modules/Makefile.in b/src/modules/Makefile.in
new file mode 100644 (file)
index 0000000..a0a8db5
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# Makefile     Makefile for the cistron-radius package.
+#
+# Version:     @(#)Makefile  1.00 01-Jul-1999  miquels@cistron.nl
+#
+
+@INCLUDE@ @IQUOTE@../../Make.inc@IQUOTE@
+
+WHAT_TO_MAKE   = all
+
+all:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+clean:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+       @rm -f *~
+
+install:
+       @$(MAKE) $(MFLAGS) WHAT_TO_MAKE=$@ common
+
+common:
+       @for mod in $(MODULES); do \
+               dir=`echo $$mod | sed -e 's/\..*$$//'`; \
+               what=$(WHAT_TO_MAKE); \
+               [ "$$what" = "all" ] && what=$$mod; \
+               echo "Making $$what in $$dir..."; \
+               (cd $$dir ; $(MAKE) $(MFLAGS) $$what) || exit 1;\
+       done
+
diff --git a/src/modules/README.modules b/src/modules/README.modules
new file mode 100644 (file)
index 0000000..f3f6961
--- /dev/null
@@ -0,0 +1,72 @@
+
+Each module has a name and 5 entry points.
+
+char *name;
+
+  Unique name, that can be used with "Auth-Type = name".
+  In that case, module->authenticate is called
+
+int init(int argc, char **argv);
+
+  (Re-)initializes the module. Is also called at SIGHUP. The arguments
+  passed are the extra arguments after the module name in /etc/raddb/modules
+
+  Returns:      0      on success
+               -1      on failure
+
+int authorize(REQUEST *request, char *username,
+               VALUE_PAIR **check_items, VALUE_PAIR **reply_items);
+
+  Looks up the user. For example, the authorize() function in rlm_files.c
+  scans the "users" file for the username and fills out check_items
+  and reply_items.
+
+  Returns:      0 RLM_AUTZ_OK        on success
+               -1 RLM_AUTZ_NOTFOUND  on success, but user not found
+                -2 RLM_AUTZ_FAIL      on failure
+               -3 RLM_AUTZ_REJECT    reject user
+                1 RLM_AUTZ_HANDLED   on success, but don't reply
+
+  If there are multiple authorization modules, they are executed sequentially
+  until one doesn't return with RLM_NOTFOUND.
+
+  On RLM_AUTZ_FAIL, we don't continue with the authentication stage but quit
+  right away without sending a reply to the origination server. This is
+  useful if for example we cannot (temporarily) connect to a SQL or LDAP
+  server, so that the client will retry or fail over to a backup server.
+
+  RLM_AUTZ_HANDLED means the function itself sent (or will send) the reply
+  to the client, so don't continue with the authentication stage.
+
+int authenticate(*authenticate)(REQUEST *request, char *username,
+               char *password);
+
+  Authenticates the user. This is called if the check-item returned by
+  the authorization contains an Auth-Type = "name" where "name" is
+  the name of the module.
+
+  Returns:     -2 RLM_AUTH_FAIL     on failed authentication and we do not
+                                    want to send a reply to the client.
+               -1 RLM_AUTH_REJECT   on failed authorization and we want to
+                                    reject the user.
+                0 RLM_AUTH_OK       User authenticated OK
+                1 RLM_AUTH_HANDLED  User authenticated OK, and the authenticate
+                                    function sent the reply to the client.
+
+int accounting(REQUEST *request)
+
+  Does accounting. All registered accounting functions are called in
+  order, even if one or more of them fails. Only when RLM_HANDLED is
+  returned the loop breaks. If one or more accouting functions failed, a
+  reply is not sent to the client (so that the client retries).
+
+  Returns:     -2 RLM_ACCT_FAIL        Accounting failed
+               -1 RLM_ACCT_FAIL_SOFT   Accounting failed, but ignore
+                0 RLM_ACCT_OK          Accounting OK
+                1 RLM_ACCT_HANDLED     OK, and already sent reply to client
+int detach(void);
+
+  Unregister all compare functions, deallocate all memory, close
+  all connections etc. Prepare to be unloaded (if loadable module).
+
diff --git a/src/modules/checkconfig b/src/modules/checkconfig
new file mode 100755 (executable)
index 0000000..566809d
--- /dev/null
@@ -0,0 +1,346 @@
+#!/bin/sh
+
+usage() {
+    cat <<EOF
+Usage: checkconfig [opts] DEFINE thingy bar
+ Echoes DEFINE to config.mak and config.h IF the conditions match.
+
+  -c LIBFOO function
+     Check if 'function' can be used without linking a library
+
+  -l LIBFOO function -lfoo ["additional compilation flags"]
+     Check if 'function' is defined in library 'foo'
+
+  -I HAVE_INCLUDE foo.h
+     Check if include file <foo.h> exists.
+
+  -f HAVE_FILE /path/to/file
+     Check if the specified file exists
+
+  -d HAVE_DIR /path/to/dir/
+     Check if the specified directory exists
+
+  -e PROGRAM program
+     Find out where the specified executable lives.
+
+EOF
+    exit 0
+}
+
+#######################################################################
+#
+# print out help
+#
+#######################################################################
+if [ "$#" -le "2" ];then
+  usage
+fi
+
+DEF=$2
+
+#######################################################################
+#
+# Check to see if a variable by the name of DEF is already defined.
+# If so, don't bother doing the check.
+#
+#######################################################################
+if [ -e config.mak ];then
+  ALREADY=`grep -w ^$DEF config.mak`
+  if [ "$ALREADY" != "" ];then
+    exit 0
+  fi
+fi
+
+#######################################################################
+#
+#  Define a function used to compile things
+#
+#######################################################################
+compile() {
+gcc $CFLAGS $LIBS tmp$$.c -o tmp$$ 2>/dev/null 1>/dev/null
+if [ "$?" = "0" ];then
+  echo yes
+  echo $DEF=$LIBS >>config.mak
+  if [ "$CFLAGS" != "" ];then
+    echo ${DEF}_CFLAGS=$CFLAGS >> config.mak
+  fi
+  echo "#define $DEF" 1 >> config.h
+else
+  echo no
+fi
+rm -f tmp$$.c tmp$$ 
+}
+
+#######################################################################
+#
+#  Do whatever check we've been asked to perform
+#
+#######################################################################
+case "$1" in
+
+#######################################################################
+#
+# -l: See if a library exists by trying to reference a function in it.
+#
+#######################################################################
+  -l)
+
+if [ "$#" -lt "4" ];then
+    usage
+fi
+
+if [ "$#" = "5" ];then
+  CFLAGS=$5
+fi
+
+FUNCTION=$3
+LIBS=$4
+
+echo -n "checking for $FUNCTION in $LIBS ... "
+
+cat >tmp$$.c <<EOF
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $FUNCTION();
+
+int main(int argc, char **argv)
+{
+  $FUNCTION();
+  return 0;
+}
+EOF
+compile
+;;
+
+#######################################################################
+#
+# -I: See if an include file exists, by trying to #include it.
+#
+#######################################################################
+  -I)
+
+if [ "$#" -lt "3" ];then
+    usage
+fi
+
+INCLUDE=$3
+if [ "$#" = "4" ];then
+  CFLAGS=$4
+fi
+
+echo -n "checking for $INCLUDE ... "
+
+cat >tmp$$.c <<EOF
+#include <$INCLUDE>
+
+int main(int argc, char **argv)
+{
+  return 0;
+}
+EOF
+compile
+;;
+
+#######################################################################
+#
+# -p: See if an include file defines a particular prototype
+#
+# (sigh) this doesn't work.  I'm not sure how to get it to work, either.
+#
+#######################################################################
+  -p)
+if [ "$#" -lt "4" ];then
+    usage
+fi
+
+if [ "$#" = "5" ];then
+  CFLAGS=$5
+fi
+
+FUNCTION=$3
+INCLUDE=$4
+
+echo -n "checking if $INCLUDE has a prototype for $FUNCTION ... "
+
+cat >tmp$$.c <<EOF
+#include <$INCLUDE>
+
+int main(int argc, char **argv)
+{
+  void *foo=$FUNCTION;
+  return 0;
+}
+EOF
+compile
+;;
+
+#######################################################################
+#
+# -c: See if a function exists WITHOUT including a library
+#
+#######################################################################
+  -c)
+
+if [ "$#" != "3" ];then
+    usage
+fi
+
+FUNCTION=$3
+
+echo -n "checking if $FUNCTION exists ... "
+
+cat >tmp$$.c <<EOF
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $FUNCTION();
+
+int main(int argc, char **argv)
+{
+  $FUNCTION();
+  return 0;
+}
+EOF
+compile
+;;
+
+#######################################################################
+#
+# -f: see if a file exists
+#
+#######################################################################
+  -f)
+if [ "$#" != "3" ];then
+    usage
+fi
+
+FILE=$3
+
+echo -n "checking what to use for $DEF ... "
+
+# see if it's a file
+if [ -f $FILE ];then
+  echo $FILE
+  echo $DEF=$FILE >> config.mak
+  echo "#define $DEF \"$FILE\"" >> config.h
+else
+  echo
+fi
+;;
+
+#######################################################################
+#
+# -d: see if a directory exists
+#
+#######################################################################
+  -d)
+if [ "$#" != "3" ];then
+    usage
+fi
+
+DIR=$3
+
+echo -n "checking what to use for $DEF ... "
+
+if [ -d $DIR ];then
+  echo $DIR
+  echo $DEF=$DIR >> config.mak
+  echo "#define $DEF \"$DIR\"" >> config.h
+else
+  echo
+fi
+;;
+
+#######################################################################
+#
+# -e: find out where an executable exists
+#
+#######################################################################
+  -e)
+if [ "$#" != "3" ];then
+    usage
+fi
+
+FILE=$3
+
+echo -n "checking for $FILE ... "
+
+dummy=`echo $PATH:/usr/ucb | sed 's/:/ /g;s/\/ //g;'`
+for dir in $dummy; do 
+  if [ -f $dir/$FILE ]; then
+    LOCATION=$dir/$FILE
+    break
+  fi
+done
+
+# see if it's a file
+if [ -f $LOCATION ];then
+  echo $LOCATION
+  echo $DEF=$LOCATION >> config.mak
+  echo "#define $DEF \"$LOCATION\"" >> config.h
+else
+  echo
+fi
+;;
+
+#######################################################################
+#
+# -s: See if an include file defines a particular structure
+#
+#  This doesn't work quite right now, as we have to have it automatically
+# include the appropriate library but...
+#
+#######################################################################
+  -s)
+if [ "$#" -lt "4" ];then
+    usage
+fi
+
+if [ "$#" = "5" ];then
+  CFLAGS=$5
+fi
+
+STRUCTURE=$3
+INCLUDE=$4
+
+echo -n "checking for $INCLUDE that defines $STRUCTURE ... "
+
+cat >tmp$$.c <<EOF
+#include <$INCLUDE>
+
+int main(int argc, char **argv)
+{
+  $STRUCTURE *foo;
+  return 0;
+}
+EOF
+
+gcc $CFLAGS tmp$$.c -o tmp$$ 2>/dev/null 1>/dev/null
+if [ "$?" = "0" ];then
+  echo yes
+  echo $DEF=$INCLUDE >>config.mak
+  if [ "$CFLAGS" != "" ];then
+    echo ${DEF}_CFLAGS=$CFLAGS >> config.mak
+  fi
+  echo "#ifdef USE_${DEF}" >> config.h
+  echo "#include <$INCLUDE>" >> config.h
+  echo "#endif USE_${DEF}" >> config.h
+else
+  echo no
+fi
+rm -f tmp$$.c tmp$$ 
+
+;;
+
+#######################################################################
+#
+# Anything else
+#
+#######################################################################
+  *)
+  usage
+;;
+
+esac
+exit 0
diff --git a/src/modules/rlm_example/Makefile b/src/modules/rlm_example/Makefile
new file mode 100644 (file)
index 0000000..e0c0350
--- /dev/null
@@ -0,0 +1,6 @@
+TARGET = rlm_example
+
+SRCS   = rlm_example.c
+
+include ../rules.mak
+
diff --git a/src/modules/rlm_example/rlm_example.c b/src/modules/rlm_example/rlm_example.c
new file mode 100644 (file)
index 0000000..a524699
--- /dev/null
@@ -0,0 +1,33 @@
+#include "autoconf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "radiusd.h"
+#include "modules.h"
+
+static int radius_init(int argc, char **argv)
+{
+  return 0;
+}
+
+static int radius_authenticate(REQUEST *request, char *username, char *password)
+{
+  return RLM_AUTH_OK;
+}
+
+static int radius_accounting(REQUEST *request)
+{
+  return RLM_ACCT_OK;
+}
+
+/* globally exported name */
+module_t rlm_example = {
+  "example",
+  0,                           /* type: reserved */
+  radius_init,                 /* initialization */
+  NULL,                                /* authorization */
+  radius_authenticate,         /* authentication */
+  radius_accounting,           /* accounting */
+  NULL,                                /* detach */
+};
diff --git a/src/modules/rlm_files/Makefile b/src/modules/rlm_files/Makefile
new file mode 100644 (file)
index 0000000..678f5d3
--- /dev/null
@@ -0,0 +1,4 @@
+TARGET = rlm_files
+SRCS   = rlm_files.c
+
+include ../rules.mak
diff --git a/src/modules/rlm_files/rlm_files.c b/src/modules/rlm_files/rlm_files.c
new file mode 100644 (file)
index 0000000..eef2717
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * rlm_files.c authorization: Find a user in the "users" file.
+ *             accounting:    Write the "detail" files.
+ *
+ * Version:     @(#)rlm_files.c  1.00  07-Aug-1999  miquels@cistron.nl
+ *
+ */
+
+char rlm_files_sccsid[] =
+"@(#)rlm_files.c       1.00 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <sys/stat.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <netdb.h>
+#include       <pwd.h>
+#include       <grp.h>
+#include       <time.h>
+#include       <ctype.h>
+#include       <fcntl.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+#include       "modules.h"
+
+#ifdef WITH_DBM
+#  include     <dbm.h>
+#endif
+#ifdef WITH_NDBM
+#  include     <ndbm.h>
+#endif
+
+#ifdef WITH_NDBM
+static DBM     *dbmfile;
+#endif
+
+PAIR_LIST      *users = NULL;
+
+#if defined(WITH_DBM) || defined(WITH_NDBM)
+/*
+ *     See if a potential DBM file is present.
+ */
+static int checkdbm(char *users, char *ext)
+{
+       char buffer[256];
+       struct stat st;
+
+       strcpy(buffer, users);
+       strcat(buffer, ext);
+
+       return stat(buffer, &st);
+}
+
+/*
+ *     Find the named user in the DBM user database.
+ *     Returns: -1 not found
+ *               0 found but doesn't match.
+ *               1 found and matches.
+ */
+static int dbm_find(char *name, VALUE_PAIR *request_pairs,
+               VALUE_PAIR **check_pairs, VALUE_PAIR **reply_pairs)
+{
+       datum           named;
+       datum           contentd;
+       char            *ptr;
+       VALUE_PAIR      *check_tmp;
+       VALUE_PAIR      *reply_tmp;
+       int             ret = 0;
+
+       named.dptr = name;
+       named.dsize = strlen(name);
+#ifdef WITH_DBM
+       contentd = fetch(named);
+#endif
+#ifdef WITH_NDBM
+       contentd = dbm_fetch(dbmfile, named);
+#endif
+       if(contentd.dptr == NULL)
+               return -1;
+
+       check_tmp = NULL;
+       reply_tmp = NULL;
+
+       /*
+        *      Parse the check values
+        */
+       ptr = contentd.dptr;
+       contentd.dptr[contentd.dsize] = '\0';
+
+       if (*ptr != '\n' && userparse(ptr, &check_tmp) != 0) {
+               log(L_ERR|L_CONS, "Parse error (check) for user %s", name);
+               pairfree(check_tmp);
+               return -1;
+       }
+       while(*ptr != '\n' && *ptr != '\0') {
+               ptr++;
+       }
+       if(*ptr != '\n') {
+               log(L_ERR|L_CONS, "Parse error (no reply pairs) for user %s",
+                       name);
+               pairfree(check_tmp);
+               return -1;
+       }
+       ptr++;
+
+       /*
+        *      Parse the reply values
+        */
+       if (userparse(ptr, &reply_tmp) != 0) {
+               log(L_ERR|L_CONS, "Parse error (reply) for user %s", name);
+               pairfree(check_tmp);
+               pairfree(reply_tmp);
+               return -1;
+       }
+
+       /*
+        *      See if the check_pairs match.
+        */
+       if (paircmp(request_pairs, check_tmp, reply_pairs) == 0) {
+               ret = 1;
+               pairmove(reply_pairs, &reply_tmp);
+               pairmove2(reply_pairs, &reply_tmp, PW_FALL_THROUGH);
+               pairmove(check_pairs, &check_tmp);
+       }
+       pairfree(reply_tmp);
+       pairfree(check_tmp);
+
+       return ret;
+}
+#endif /* DBM */
+
+
+#ifdef WITH_ASCEND_HACK
+/*
+ *     dgreer --
+ *     This hack changes Ascend's wierd port numberings
+ *      to standard 0-??? port numbers so that the "+" works
+ *      for IP address assignments.
+ */
+static int ascend_port_number(int nas_port)
+{
+       int service;
+       int line;
+       int channel;
+
+       if (nas_port > 9999) {
+               service = nas_port/10000; /* 1=digital 2=analog */
+               line = (nas_port - (10000 * service)) / 100;
+               channel = nas_port-((10000 * service)+(100 * line));
+               nas_port =
+                       (channel - 1) + (line - 1) * ASCEND_CHANNELS_PER_LINE;
+       }
+       return nas_port;
+}
+#endif
+
+/*
+ *     See if a VALUE_PAIR list contains Fall-Through = Yes
+ */
+static int fallthrough(VALUE_PAIR *vp)
+{
+       VALUE_PAIR *tmp;
+       tmp = pairfind(vp, PW_FALL_THROUGH);
+       return tmp ? tmp->lvalue : 0;
+}
+
+/*
+ *     (Re-)read the "users" file into memory.
+ */
+static int file_init(int argc, char **argv)
+{
+       char            fn[1024];
+       char            *ptr;
+
+       ptr = argv[0] ? argv[0] : RADIUS_USERS;
+       sprintf(fn, "%s/%s", radius_dir, ptr);
+
+#if defined(WITH_DBM) || defined(WITH_NDBM)
+       if (!use_dbm &&
+           (checkdbm(ptr, ".dir") == 0 ||
+            checkdbm(ptr, ".db") == 0)) {
+               log(L_INFO|L_CONS, "DBM files found but no -b flag "
+                       "given - NOT using DBM");
+       }
+#endif
+
+       if (!use_dbm) users = pairlist_read(fn, 1);
+
+       return users ? 0 : -1;
+}
+
+/*
+ *     Find the named user in the database.  Create the
+ *     set of attribute-value pairs to check and reply with
+ *     for this user from the database. The main code only
+ *     needs to check the password, the rest is done here.
+ */
+static int file_authorize(REQUEST *request, char *name,
+               VALUE_PAIR **check_pairs, VALUE_PAIR **reply_pairs)
+{
+       int             nas_port = 0;
+       VALUE_PAIR      *request_pairs;
+       VALUE_PAIR      *check_tmp;
+       VALUE_PAIR      *reply_tmp;
+       VALUE_PAIR      *tmp, *tmp2;
+       PAIR_LIST       *pl;
+       int             found = 0;
+#if defined(WITH_DBM) || defined(WITH_NDBM)
+       int             i, r;
+       char            buffer[256];
+#endif
+
+       request_pairs = request->packet->vps;
+
+       /*
+        *      Find the NAS port ID.
+        */
+       if ((tmp = pairfind(request_pairs, PW_NAS_PORT_ID)) != NULL)
+               nas_port = tmp->lvalue;
+
+       /*
+        *      Find the entry for the user.
+        */
+#if defined(WITH_DBM) || defined(WITH_NDBM)
+       /*
+        *      FIXME: move to rlm_dbm.c
+        */
+       if (use_dbm) {
+               /*
+                *      FIXME: No Prefix / Suffix support for DBM.
+                */
+               sprintf(buffer, "%s/%s", radius_dir, RADIUS_USERS);
+#ifdef WITH_DBM
+               if (dbminit(buffer) != 0)
+#endif
+#ifdef WITH_NDBM
+               if ((dbmfile = dbm_open(buffer, O_RDONLY, 0)) == NULL)
+#endif
+               {
+                       log(L_ERR|L_CONS, "cannot open dbm file %s",
+                               buffer);
+                       return RLM_AUTZ_FAIL;
+               }
+
+               r = dbm_find(name, request_pairs, check_pairs, reply_pairs);
+               if (r > 0) found = 1;
+               if (r <= 0 || fallthrough(*reply_pairs)) {
+
+                       pairdelete(reply_pairs, PW_FALL_THROUGH);
+
+                       sprintf(buffer, "DEFAULT");
+                       i = 0;
+                       while ((r = dbm_find(buffer, request_pairs,
+                              check_pairs, reply_pairs)) >= 0 || i < 2) {
+                               if (r > 0) {
+                                       found = 1;
+                                       if (!fallthrough(*reply_pairs))
+                                               break;
+                                       pairdelete(reply_pairs,PW_FALL_THROUGH);
+                               }
+                               sprintf(buffer, "DEFAULT%d", i++);
+                       }
+               }
+#ifdef WITH_DBM
+               dbmclose();
+#endif
+#ifdef WITH_NDBM
+               dbm_close(dbmfile);
+#endif
+       } else
+       /*
+        *      Note the fallthrough through the #endif.
+        */
+#endif
+
+       for(pl = users; pl; pl = pl->next) {
+
+               if (strcmp(name, pl->name) && strcmp(pl->name, "DEFAULT"))
+                       continue;
+
+               if (paircmp(request_pairs, pl->check, reply_pairs) == 0) {
+                       DEBUG2("  users: Matched %s at %d",
+                              pl->name, pl->lineno);
+                       found = 1;
+                       check_tmp = paircopy(pl->check);
+                       reply_tmp = paircopy(pl->reply);
+                       pairmove(reply_pairs, &reply_tmp);
+                       pairmove(check_pairs, &check_tmp);
+                       pairfree(reply_tmp);
+                       pairfree(check_tmp);
+
+                       /*
+                        *      Fallthrough?
+                        */
+                       if (!fallthrough(pl->reply))
+                               break;
+               }
+       }
+
+       /*
+        *      See if we succeeded.
+        */
+       if (!found)
+               return RLM_AUTZ_NOTFOUND; /* didn't find the user */
+
+       /*
+        *      Add the port number to the Framed-IP-Address if
+        *      vp->addport is set, or if the Add-Port-To-IP-Address
+        *      pair is present.
+        *
+        *      FIXME: this should not happen here, but
+        *      after module_authorize in the main code!
+        */
+       if ((tmp = pairfind(*reply_pairs, PW_FRAMED_IP_ADDRESS)) != NULL) {
+               tmp2 = pairfind(*reply_pairs, PW_ADD_PORT_TO_IP_ADDRESS);
+               if (tmp->addport || (tmp2 && tmp2->lvalue)) {
+#ifdef WITH_ASCEND_HACK
+                       nas_port = ascend_port_number(nas_port);
+#endif
+                       tmp->lvalue = htonl(ntohl(tmp->lvalue) + nas_port);
+                       tmp->addport = 0;
+               }
+               pairdelete(reply_pairs, PW_ADD_PORT_TO_IP_ADDRESS);
+       }
+
+       /*
+        *      Remove server internal parameters.
+        */
+       pairdelete(reply_pairs, PW_FALL_THROUGH);
+
+       return RLM_AUTZ_OK;
+}
+
+/*
+ *     Authentication - unused.
+ */
+static int file_authenticate(REQUEST *request, char *username, char *password)
+{
+       return RLM_AUTH_OK;
+}
+
+/*
+ *     Accounting - write the detail files.
+ */
+static int file_accounting(REQUEST *request)
+{
+       FILE            *outfd;
+       char            nasname[128];
+       char            buffer[512];
+       char            *s;
+       VALUE_PAIR      *pair;
+       UINT4           nas;
+       NAS             *cl;
+       long            curtime;
+       int             ret = RLM_ACCT_OK;
+       struct stat     st;
+
+       /*
+        *      See if we have an accounting directory. If not,
+        *      return.
+        */
+       if (stat(radacct_dir, &st) < 0)
+               return RLM_ACCT_OK;
+       curtime = time(0);
+
+       /*
+        *      Find out the name of this terminal server. We try
+        *      to find the PW_NAS_IP_ADDRESS in the naslist file.
+        *      If that fails, we look for the originating address.
+        *      Only if that fails we resort to a name lookup.
+        */
+       cl = NULL;
+       nas = request->packet->src_ipaddr;
+       if ((pair = pairfind(request->packet->vps, PW_NAS_IP_ADDRESS)) != NULL)
+               nas = pair->lvalue;
+       if (request->proxy && request->proxy->src_ipaddr)
+               nas = request->proxy->src_ipaddr;
+
+       if ((cl = nas_find(nas)) != NULL) {
+               if (cl->shortname[0])
+                       strcpy(nasname, cl->shortname);
+               else
+                       strcpy(nasname, cl->longname);
+       }
+
+       if (cl == NULL) {
+               s = ip_hostname(nas);
+               if (strlen(s) >= sizeof(nasname) || strchr(s, '/'))
+                       return -1;
+               strcpy(nasname, s);
+       }
+
+       /*
+        *      Create a directory for this nas.
+        */
+       sprintf(buffer, "%s/%s", radacct_dir, nasname);
+       (void) mkdir(buffer, 0755);
+
+       /*
+        *      Write Detail file.
+        */
+       sprintf(buffer, "%s/%s/%s", radacct_dir, nasname, "detail");
+       if ((outfd = fopen(buffer, "a")) == NULL) {
+               log(L_ERR, "Acct: Couldn't open file %s", buffer);
+               ret = RLM_ACCT_FAIL;
+       } else {
+
+               /* Post a timestamp */
+               fputs(ctime(&curtime), outfd);
+
+               /* Write each attribute/value to the log file */
+               pair = request->packet->vps;
+               while (pair) {
+                       if (pair->attribute != PW_PASSWORD) {
+                               fputs("\t", outfd);
+                               fprint_attr_val(outfd, pair);
+                               fputs("\n", outfd);
+                       }
+                       pair = pair->next;
+               }
+
+               /*
+                *      Add non-protocol attibutes.
+                */
+               fprintf(outfd, "\tTimestamp = %ld\n", curtime);
+               if (request->packet->verified)
+                       fputs("\tRequest-Authenticator = Verified\n", outfd);
+               else
+                       fputs("\tRequest-Authenticator = None\n", outfd);
+               fputs("\n", outfd);
+               fclose(outfd);
+       }
+
+       return ret;
+}
+
+
+/*
+ *     Clean up.
+ */
+static int file_detach(void)
+{
+       pairlist_free(&users);
+       return 0;
+}
+
+
+/* globally exported name */
+module_t rlm_files = {
+       "files",
+       0,                              /* type: reserved */
+       file_init,                      /* initialization */
+       file_authorize,                 /* authorization */
+       file_authenticate,              /* authentication */
+       file_accounting,                /* accounting */
+       file_detach,                    /* detach */
+};
+
diff --git a/src/modules/rlm_pam/Makefile b/src/modules/rlm_pam/Makefile
new file mode 100644 (file)
index 0000000..a37acc8
--- /dev/null
@@ -0,0 +1,8 @@
+TARGET = rlm_pam
+SRCS   = rlm_pam.c
+LIBS   = -lpam -ldl
+
+include ../rules.mak
+
+config.mak:
+       @../checkconfig -l LIBPAM pam_start -lpam -ldl
diff --git a/src/modules/rlm_pam/rlm_pam.c b/src/modules/rlm_pam/rlm_pam.c
new file mode 100644 (file)
index 0000000..996bdae
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * pam.c       Functions to access the PAM library. This was taken
+ *             from the hacks that miguel a.l. paraz <map@iphil.net>
+ *             did on radiusd-cistron-1.5.3 and migrated to a
+ *             separate file.
+ *
+ *             That, in fact, was again based on the original stuff
+ *             from Jeph Blaize <jab@kiva.net> done in May 1997.
+ *
+ * Version:    @(#)pam.c  1.10  14-Jul-1998  cdent@kiva.net
+ *
+ */
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <string.h>
+#include       <pwd.h>
+#include       <time.h>
+#include       <ctype.h>
+
+#ifdef WITH_PAM
+#  include     <security/pam_appl.h>
+#endif
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+#include       "modules.h"
+
+#ifdef WITH_PAM
+/*************************************************************************
+ *
+ *     Function: PAM_conv
+ *
+ *     Purpose: Dialogue between RADIUS and PAM modules.
+ *
+ * jab - stolen from pop3d
+ *************************************************************************/
+
+static char *PAM_username;
+static char *PAM_password;
+static int PAM_error =0;
+
+static int PAM_conv (int num_msg,
+                     const struct pam_message **msg,
+                     struct pam_response **resp,
+                     void *appdata_ptr) {
+  int count = 0, replies = 0;
+  struct pam_response *reply = NULL;
+  int size = sizeof(struct pam_response);
+  
+#define GET_MEM if (reply) realloc(reply, size); else reply = malloc(size); \
+  if (!reply) return PAM_CONV_ERR; \
+  size += sizeof(struct pam_response)
+#define COPY_STRING(s) (s) ? strdup(s) : NULL
+                                    
+  for (count = 0; count < num_msg; count++) {
+    switch (msg[count]->msg_style) {
+    case PAM_PROMPT_ECHO_ON:
+      GET_MEM;
+      reply[replies].resp_retcode = PAM_SUCCESS;
+      reply[replies++].resp = COPY_STRING(PAM_username);
+      /* PAM frees resp */
+      break;
+    case PAM_PROMPT_ECHO_OFF:
+      GET_MEM;
+      reply[replies].resp_retcode = PAM_SUCCESS;
+      reply[replies++].resp = COPY_STRING(PAM_password);
+      /* PAM frees resp */
+      break;
+    case PAM_TEXT_INFO:
+      /* ignore it... */
+      break;
+    case PAM_ERROR_MSG:
+    default:
+      /* Must be an error of some sort... */
+      free (reply);
+      PAM_error = 1;
+      return PAM_CONV_ERR;
+    }
+  }
+  if (reply) *resp = reply;
+
+  return PAM_SUCCESS;
+}
+
+struct pam_conv conv = {
+  PAM_conv,
+  NULL
+};
+
+/*************************************************************************
+ *
+ *     Function: pam_pass
+ *
+ *     Purpose: Check the users password against the standard UNIX
+ *              password table + PAM.
+ *
+ * jab start 19970529
+ *************************************************************************/
+
+/* cjd 19980706
+ * 
+ * for most flexibility, passing a pamauth type to this function
+ * allows you to have multiple authentication types (i.e. multiple
+ * files associated with radius in /etc/pam.d)
+ */
+static int pam_pass(char *name, char *passwd, const char *pamauth)
+{
+    pam_handle_t *pamh=NULL;
+    int retval;
+
+    PAM_username = name;
+    PAM_password = passwd;
+
+    DEBUG("pam_pass: using pamauth string <%s> for pam.conf lookup", pamauth);
+    retval = pam_start(pamauth, name, &conv, &pamh);
+    if (retval != PAM_SUCCESS) {
+      DEBUG("pam_pass: function pam_start FAILED for <%s>. Reason: %s",
+           name, pam_strerror(pamh, retval));
+      return -1;
+    }
+
+    retval = pam_authenticate(pamh, 0);
+    if (retval != PAM_SUCCESS) {
+      DEBUG("pam_pass: function pam_authenticate FAILED for <%s>. Reason: %s",
+           name, pam_strerror(pamh, retval));
+      pam_end(pamh, 0);
+      return -1;
+    }
+
+    retval = pam_acct_mgmt(pamh, 0);
+    if (retval != PAM_SUCCESS) {
+      DEBUG("pam_pass: function pam_acct_mgmt FAILED for <%s>. Reason: %s",
+           name, pam_strerror(pamh, retval));
+      pam_end(pamh, 0);
+      return -1;
+    }
+
+    DEBUG("pam_pass: authentication succeeded for <%s>", name);
+    pam_end(pamh, 0);
+    return 0;
+}
+
+/* translate between function declarations */
+static int pam_auth(REQUEST *request, char *username, char *password)
+{
+       int     r;
+
+       r = pam_pass(username, password, "radiusd");
+       return (r == 0) ? RLM_AUTH_OK : RLM_AUTH_REJECT;
+}
+
+#else /* WITH_PAM */
+
+static int pam_auth(REQUEST *request, char *username, char *password)
+{
+       return RLM_AUTH_REJECT;
+}
+
+#endif
+
+module_t rlm_pam = {
+  "PAM",
+  0,                           /* type: reserved */
+  NULL,                                /* initialize */
+  NULL,                                /* authorize */
+  pam_auth,                    /* authenticate */
+  NULL,                                /* accounting */
+  NULL,                                /* detach */
+};
+
diff --git a/src/modules/rlm_preprocess/Makefile b/src/modules/rlm_preprocess/Makefile
new file mode 100644 (file)
index 0000000..3264440
--- /dev/null
@@ -0,0 +1,4 @@
+TARGET = rlm_preprocess
+SRCS   = rlm_preprocess.c
+
+include ../rules.mak
diff --git a/src/modules/rlm_preprocess/rlm_preprocess.c b/src/modules/rlm_preprocess/rlm_preprocess.c
new file mode 100644 (file)
index 0000000..01aa308
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * rlm_preprocess.c
+ *             Contains the functions for the "huntgroups" and "hints"
+ *             files.
+ *
+ * Version:     @(#)rlm_preprocess.c  1.00  09-Aug-1999  miquels@cistron.nl
+ *
+ */
+
+char rlm_preprocess_sccsid[] =
+"@(#)rlm_preprocess.c  1.00 Copyright 1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+#include       <sys/stat.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <time.h>
+#include       <ctype.h>
+
+#if HAVE_MALLOC_H
+#  include     <malloc.h>
+#endif
+
+#include       "radiusd.h"
+#include       "modules.h"
+
+
+static PAIR_LIST       *huntgroups;
+static PAIR_LIST       *hints;
+
+/*
+ *     Compare the request with the "reply" part in the
+ *     huntgroup, which normally only contains username or group.
+ *     At least one of the "reply" items has to match.
+ */
+static int hunt_paircmp(VALUE_PAIR *request, VALUE_PAIR *check)
+{
+       VALUE_PAIR      *check_item = check;
+       VALUE_PAIR      *tmp;
+       int             result = -1;
+
+       if (check == NULL) return 0;
+
+       while (result != 0 && check_item != NULL) {
+
+               tmp = check_item->next;
+               check_item->next = NULL;
+
+               result = paircmp(request, check_item, NULL);
+
+               check_item->next = tmp;
+               check_item = check_item->next;
+       }
+
+       return result;
+}
+
+
+/*
+ *     Compare prefix/suffix
+ */
+static int presufcmp(VALUE_PAIR *check, char *name, char *rest)
+{
+       int             len, namelen;
+       int             ret = -1;
+
+#if 0 /* DEBUG */
+       printf("Comparing %s and %s, check->attr is %d\n",
+               name, check->strvalue, check->attribute);
+#endif
+
+       len = strlen(check->strvalue);
+       switch (check->attribute) {
+               case PW_PREFIX:
+                       ret = strncmp(name, check->strvalue, len);
+                       if (ret == 0 && rest)
+                               strcpy(rest, name + len);
+                       break;
+               case PW_SUFFIX:
+                       namelen = strlen(name);
+                       if (namelen < len)
+                               break;
+                       ret = strcmp(name + namelen - len, check->strvalue);
+                       if (ret == 0 && rest) {
+                               strncpy(rest, name, namelen - len);
+                               rest[namelen - len] = 0;
+                       }
+                       break;
+       }
+
+       return ret;
+}
+
+/*
+ *     Match a username with a wildcard expression.
+ *     Is very limited for now.
+ */
+static int matches(char *name, PAIR_LIST *pl, char *matchpart)
+{
+       int len, wlen;
+       int ret = 0;
+       char *wild = pl->name;
+       VALUE_PAIR *tmp;
+
+       /*
+        *      We now support both:
+        *
+        *              DEFAULT Prefix = "P"
+        *
+        *      and
+        *              P*
+        */
+       if ((tmp = pairfind(pl->check, PW_PREFIX)) != NULL ||
+           (tmp = pairfind(pl->check, PW_SUFFIX)) != NULL) {
+
+               if (strncmp(pl->name, "DEFAULT", 7) == 0 ||
+                   strcmp(pl->name, name) == 0)
+                       return !presufcmp(tmp, name, matchpart);
+       }
+
+       /*
+        *      Shortcut if there's no '*' in pl->name.
+        */
+       if (strchr(pl->name, '*') == NULL &&
+           (strncmp(pl->name, "DEFAULT", 7) == 0 ||
+            strcmp(pl->name, name) == 0)) {
+               strcpy(matchpart, name);
+               return 1;
+       }
+
+       /*
+        *      Normally, we should return 0 here, but we
+        *      support the old * stuff.
+        */
+       len = strlen(name);
+       wlen = strlen(wild);
+
+       if (len == 0 || wlen == 0) return 0;
+
+       if (wild[0] == '*') {
+               wild++;
+               wlen--;
+               if (wlen <= len && strcmp(name + (len - wlen), wild) == 0) {
+                       strcpy(matchpart, name);
+                       matchpart[len - wlen] = 0;
+                       ret = 1;
+               }
+       } else if (wild[wlen - 1] == '*') {
+               if (wlen <= len && strncmp(name, wild, wlen - 1) == 0) {
+                       strcpy(matchpart, name + wlen - 1);
+                       ret = 1;
+               }
+       }
+
+       return ret;
+}
+
+
+/*
+ *     Add hints to the info sent by the terminal server
+ *     based on the pattern of the username.
+ */
+static int hints_setup(VALUE_PAIR *request_pairs)
+{
+       char            newname[MAX_STRING_LEN];
+       char            *name;
+       VALUE_PAIR      *add;
+       VALUE_PAIR      *last;
+       VALUE_PAIR      *tmp;
+       PAIR_LIST       *i;
+       int             do_strip;
+
+       if (hints == NULL || request_pairs == NULL)
+               return RLM_AUTZ_OK;
+
+       /* 
+        *      Check for valid input, zero length names not permitted 
+        */
+       if ((tmp = pairfind(request_pairs, PW_USER_NAME)) == NULL)
+               name = NULL;
+       else
+               name = tmp->strvalue;
+
+       if (name == NULL || name[0] == 0)
+               /*
+                *      No name, nothing to do.
+                */
+               return RLM_AUTZ_OK;
+
+       for (i = hints; i; i = i->next) {
+               if (matches(name, i, newname)) {
+                       DEBUG2("  hints: Matched %s at %d",
+                              i->name, i->lineno);
+                       break;
+               }
+       }
+
+       if (i == NULL) return RLM_AUTZ_OK;
+
+       add = paircopy(i->reply);
+
+#if 0 /* DEBUG */
+       printf("In hints_setup, newname is %s\n", newname);
+#endif
+
+       /*
+        *      See if we need to adjust the name.
+        */
+       do_strip = 1;
+       if ((tmp = pairfind(i->reply, PW_STRIP_USERNAME)) != NULL
+            && tmp->lvalue == 0)
+               do_strip = 0;
+       if ((tmp = pairfind(i->check, PW_STRIP_USERNAME)) != NULL
+            && tmp->lvalue == 0)
+               do_strip = 0;
+
+       if (do_strip) {
+               tmp = pairfind(request_pairs, PW_USER_NAME);
+               if (tmp) {
+                       strcpy(tmp->strvalue, newname);
+                       tmp->length = strlen(tmp->strvalue);
+               }
+       }
+
+       /*
+        *      Now add all attributes to the request list,
+        *      except the PW_STRIP_USERNAME one.
+        */
+       pairdelete(&add, PW_STRIP_USERNAME);
+       for(last = request_pairs; last && last->next; last = last->next)
+               ;
+       if (last) last->next = add;
+
+       return RLM_AUTZ_OK;
+}
+
+/*
+ *     See if the huntgroup matches. This function is
+ *     tied to the "Huntgroup" keyword.
+ */
+static int huntgroup_cmp(VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       PAIR_LIST       *i;
+       char            *huntgroup;
+
+       huntgroup = check->strvalue;
+
+       for (i = huntgroups; i; i = i->next) {
+               if (strcmp(i->name, huntgroup) != 0)
+                       continue;
+               if (paircmp(request, i->check, NULL) == 0) {
+                       DEBUG2("  huntgroups: Matched %s at %d",
+                              i->name, i->lineno);
+                       break;
+               }
+       }
+
+       return (i != NULL);
+}
+
+
+/*
+ *     See if we have access to the huntgroup.
+ */
+static int huntgroup_access(VALUE_PAIR *request_pairs)
+{
+       PAIR_LIST       *i;
+       int             r = 1;
+
+       if (huntgroups == NULL)
+               return RLM_AUTZ_REJECT;
+
+       for(i = huntgroups; i; i = i->next) {
+               /*
+                *      See if this entry matches.
+                */
+               if (paircmp(request_pairs, i->check, NULL) != 0)
+                       continue;
+
+               /*
+                *      Now check for access.
+                */
+               r = RLM_AUTZ_REJECT;
+               if (hunt_paircmp(request_pairs, i->reply) == 0) {
+                       r = RLM_AUTZ_OK;
+               }
+               break;
+       }
+
+       return r;
+}
+
+/*
+ *     Initialize.
+ */
+static int preprocess_init(int argc, char **argv)
+{
+       char    buffer[256];
+
+       pairlist_free(&huntgroups);
+       pairlist_free(&hints);
+
+       sprintf(buffer, "%s/%s", radius_dir, RADIUS_HUNTGROUPS);
+       huntgroups = pairlist_read(buffer, 0);
+       sprintf(buffer, "%s/%s", radius_dir, RADIUS_HINTS);
+       hints      = pairlist_read(buffer, 0);
+
+       paircompare_register(PW_HUNTGROUP_NAME, 0, huntgroup_cmp);
+
+       return 0;
+}
+
+/*
+ *     Preprocess a request.
+ */
+static int preprocess_authorize(REQUEST *request, char *name,
+       VALUE_PAIR **check_pairs, VALUE_PAIR **reply_pairs)
+{
+       hints_setup(request->packet->vps);
+       if (!huntgroup_access(request->packet->vps)) {
+               log(L_AUTH, "No huntgroup access: [%s] (%s)",
+                       request->username, auth_name(request, 1));
+               return RLM_AUTZ_REJECT;
+       }
+
+       return RLM_AUTZ_NOTFOUND; /* Meaning: try next autorization module */
+}
+
+/*
+ *     Preprocess a request before accounting
+ */
+static int preprocess_accounting(REQUEST *request)
+{
+       hints_setup(request->packet->vps);
+
+       return RLM_ACCT_OK;
+}
+
+/*
+ *      Clean up.
+ */
+static int preprocess_detach(void)
+{
+       paircompare_unregister(PW_HUNTGROUP_NAME, huntgroup_cmp);
+       pairlist_free(&huntgroups);
+       pairlist_free(&hints);
+
+       return 0;
+}
+
+/* globally exported name */
+module_t rlm_preprocess = {
+       "preprocess",
+       0,                              /* type: reserved */
+       preprocess_init,                /* initialization */
+       preprocess_authorize,           /* authorization */
+       NULL,                           /* authentication */
+       preprocess_accounting,          /* accounting */
+       preprocess_detach,              /* detach */
+};
+
diff --git a/src/modules/rlm_unix/Makefile b/src/modules/rlm_unix/Makefile
new file mode 100644 (file)
index 0000000..2128640
--- /dev/null
@@ -0,0 +1,24 @@
+TARGET = rlm_unix
+SRCS   = rlm_unix.c cache.c
+
+include ../rules.mak
+
+CFLAGS         += -DLOGDIR=\"$(LOGDIR)\"
+
+rlm_unix.c: config.h
+
+include config.mak
+
+LIBS += $(LIBSHADOW) $(LIBCRYPT)
+
+config: config.mak
+
+config.mak config.h:
+       @../checkconfig -c LIBCRYPT crypt
+       @../checkconfig -I HAVE_CRYPT_H crypt.h
+       @../checkconfig -l LIBCRYPT crypt -lcrypt
+       @../checkconfig -c HAVE_GETSPNAM getspnam
+       @../checkconfig -l LIBSHADOW getspnam -lshadow
+       @../checkconfig -f ETC_SHADOW /etc/shadow
+       @../checkconfig -I HAVE_SHADOW_H shadow.h
+       @../checkconfig -c HAVE_GETUSERSHELL getusershell
diff --git a/src/modules/rlm_unix/cache.c b/src/modules/rlm_unix/cache.c
new file mode 100644 (file)
index 0000000..be4c1cf
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * cache.c:  Offers ability to cache /etc/group, /etc/passwd, /etc/shadow,
+ *           and /var/log/radutmp 
+ *
+ * All users in the passwd/shadow files are stored in a hash table.
+ * the hash lookup is VERY fast,  generally 1.0673 comparisons per
+ * lookup.  For the unitiated, that's blazing.  You can't have less
+ * than one comparison, for example.
+ *
+ * The /etc/group file is stored in a singly linked list, as that appears
+ * to be fast enough.  It's generally a small enough file that hashing is
+ * unnecessary.
+ *
+ *     (c) 1999 Author - Jeff Carneal, Apex Internet Services, Inc.
+ *
+ * Version: cache.c  0.99  04-13-1999  jeff@apex.net
+ *
+ */    
+
+#include "autoconf.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if HAVE_MALLOC_H
+#  include <malloc.h>
+#endif
+
+#if HAVE_SHADOW_H
+#  include <shadow.h>
+#endif
+
+#if HAVE_CRYPT_H
+#  include <crypt.h>
+#endif 
+
+#include "radiusd.h"
+#include "radutmp.h"
+#include "cache.h"
+
+/* Make the tables global since so many functions rely on them */
+static struct mypasswd *hashtable[HASHTABLESIZE];
+static struct mygroup *grphead = NULL;
+
+/* Builds the hash table up by storing passwd/shadow fields
+ * in memory.  Returns -1 on failure, 0 on success.
+ */
+int buildHashTable(void) {
+       FILE *passwd;
+#if HAVE_SHADOW_H
+       FILE *shadow;
+#endif
+       char buffer[BUFSIZE];
+       char idtmp[10];
+       char username[MAXUSERNAME];
+       char *ptr, *bufptr;
+       int len, hashindex, numread=0;
+       struct mypasswd *new, *cur, *next;
+
+       memset((char *)username, 0, MAXUSERNAME);
+
+       /* Initialize the table.  This works even if we're rebuilding it */
+       for(hashindex=0; hashindex<HASHTABLESIZE; hashindex++) {
+               if(hashtable[hashindex]) {
+                       cur = hashtable[hashindex];
+                       while(cur) {
+                               next = cur->next;
+                               free(cur->pw_name);     
+                               free(cur->pw_passwd);   
+                               free(cur);      
+                               cur = next;
+                       }
+               }
+       }       
+
+       /* Init hash array */
+       memset((struct mypasswd *)hashtable, 0, (HASHTABLESIZE*(sizeof(struct mypasswd *))));
+
+       if( (passwd = fopen(PASSWDFILE, "r")) == NULL) {
+               log(L_ERR, "HASH:  Can't open file %s:  %s", PASSWDFILE, strerror(errno));
+               return -1;
+       } else {
+               while(fgets(buffer, BUFSIZE , passwd) != (char *)NULL) {
+                       numread++;
+
+                       bufptr = buffer;
+                       /* Get usernames from password file */
+                       for(ptr = bufptr; *ptr!=':'; ptr++);
+                       len = ptr - bufptr;
+                       if((len+1) > MAXUSERNAME) {
+                               log(L_ERR, "HASH:  Username too long in line: %s", buffer);
+                       }
+                       strncpy(username, buffer, len);
+                       username[len] = '\0';
+
+                       /* Hash the username */
+                       hashindex = hashUserName(username);     
+                       /*printf("%s:%d\n", username, hashindex);*/
+       
+                       /* Allocate space for structure to go in hashtable */
+                       if((new = (struct mypasswd *)malloc(sizeof(struct mypasswd))) == NULL) {
+                               log(L_ERR, "HASH:  Out of memory!");
+                               return -1;
+                       }
+                       memset((struct mypasswd *)new, 0, sizeof(struct mypasswd));
+
+                       /* Put username into new structure */
+                       if((new->pw_name = (char *)malloc(strlen(username)+1)) == NULL) {
+                               log(L_ERR, "HASH:  Out of memory!");
+                               return -1;
+                       }
+                       strncpy(new->pw_name, username, strlen(username)+1);
+
+                       /* Put passwords into array, if not shadowed */
+                       /* Get passwords from password file (shadow comes later) */
+                       ptr++;
+                       bufptr = ptr;
+                       while(*ptr!=':')
+                               ptr++;
+
+#if !HAVE_SHADOW_H
+                       /* Put passwords into new structure (*/
+                       len = ptr - bufptr;
+                       if((new->pw_passwd = (char *)malloc(len+1)) == NULL) {
+                               log(L_ERR, "HASH:  Out of memory!");
+                               return -1;
+                       }
+                       strncpy(new->pw_passwd, bufptr, len);
+                       new->pw_passwd[len] = '\0';
+#endif /* !HAVE_SHADOW_H */  
+
+                       /* 
+                   * Put uid into structure.  Not sure why, but 
+                        * at least we'll have it later if we need it
+                        */
+                       ptr++;
+                       bufptr = ptr;
+                       while(*ptr!=':')
+                               ptr++;
+                       len = ptr - bufptr;
+                       strncpy(idtmp, bufptr, len);
+                       idtmp[len] = '\0';
+                       new->pw_uid = (uid_t)atoi(idtmp);       
+
+                       /* 
+                   * Put gid into structure.  
+                        */
+                       ptr++;
+                       bufptr = ptr;
+                       while(*ptr!=':')
+                               ptr++;
+                       len = ptr - bufptr;
+                       strncpy(idtmp, bufptr, len);
+                       idtmp[len] = '\0';
+                       new->pw_gid = (gid_t)atoi(idtmp);       
+
+                       /* 
+                        * We're skipping name, home dir, and shell
+                        * as I can't think of any use for storing them
+                        */
+
+                       /*printf("User:  %s, UID:  %d, GID:  %d\n", new->pw_name, new->pw_uid, new->pw_gid);*/
+                       /* Store user in the hash */
+                       storeHashUser(new, hashindex);
+               }       /* End while(fgets(buffer, BUFSIZE , passwd) != (char *)NULL) { */
+       } /* End if */
+       fclose(passwd);
+
+#if HAVE_SHADOW_H
+       /*
+        *      FIXME: Check for password expiry!
+        */
+       if( (shadow = fopen(SHADOWFILE, "r")) == NULL) {
+               log(L_ERR, "HASH:  Can't open file %s: %s", SHADOWFILE, strerror(errno));
+               return -1;
+       } else {
+               while(fgets(buffer, BUFSIZE , shadow) != (char *)NULL) {
+
+                       bufptr = buffer;
+                       /* Get usernames from shadow file */
+                       for(ptr = bufptr; *ptr!=':'; ptr++);
+                       len = ptr - bufptr;
+                       if((len+1) > MAXUSERNAME) {
+                               log(L_ERR, "HASH:  Username too long in line:  %s", buffer);
+                       }
+                       strncpy(username, buffer, len);
+                       username[len] = '\0';
+                       if((new = findHashUser(username)) == NULL) {
+                               log(L_ERR, "HASH:  Username %s in shadow but not passwd??", username);
+                               continue;
+                       }
+
+                       /* Put passwords into struct from shadow file */
+                       ptr++;
+                       bufptr = ptr;
+                       while(*ptr!=':')
+                               ptr++;
+                       len = ptr - bufptr;
+
+                       if((new->pw_passwd = (char *)malloc(len+1)) == NULL) {
+                               log(L_ERR, "HASH:  Out of memory!");
+                               return -1;
+                       }
+                       strncpy(new->pw_passwd, bufptr, len);
+                       new->pw_passwd[len] = '\0';
+               }
+       }
+       fclose(shadow);
+#endif
+
+       /* Finally, let's look at radutmp and make a record of everyone
+    * that's logged in currently */
+       hashradutmp();
+
+       /* log how many entries we stored from the passwd file */
+       log(L_INFO, "HASH:  Stored %d entries from %s", numread, PASSWDFILE);
+
+       return 0;
+}
+
+/* This function caches the /etc/group file, so it's one less thing
+ * we have to lookup on disk.  it uses getgrent(), which is quite slow,
+ * but the group file is generally small enough that it won't matter
+ * As a side note, caching the user list per group was a major pain
+ * in the ass, and I won't even need it.  I really hope that somebody
+ * out there needs and appreciates it.
+ * Returns -1 on failure, and 0 on success
+ */
+int buildGrpList(void) {
+
+       int len, len2, index, numread=0;
+       struct group *grp;
+       struct mygroup *new, *cur, *next;
+       char **member;
+
+       cur = grphead;
+
+       /* Free up former grp list (we can use this as a rebuild function too */
+       while(cur) {
+               next = cur->next;
+
+               /* Free name, name, member list */
+               for(member = cur->gr_mem; *member; member++) {
+                       free(*member);
+               }
+               free(cur->gr_mem);
+               free(cur->gr_name);
+               free(cur->gr_passwd);
+               free(cur);
+               cur = next;
+       }                                  
+       grphead = NULL;
+       
+       /* Make sure to begin at beginning */
+       setgrent();
+
+       /* Get next entry from the group file */
+       while((grp = getgrent()) != NULL) {
+
+               /* Make new mygroup structure in mem */
+               if((new = (struct mygroup *)malloc(sizeof(struct mygroup))) == NULL) {
+                       log(L_ERR, "HASH:  (buildGrplist) Out of memory!");
+                       return -1;
+               }
+               memset((struct mygroup*)new, 0, sizeof(struct mygroup));
+       
+               /* copy grp entries to my structure */
+               len = strlen(grp->gr_name);
+               if((new->gr_name = (char *)malloc(len+1)) == NULL) {
+                       log(L_ERR, "HASH:  (buildGrplist) Out of memory!");
+                       return -1;
+               }
+               strncpy(new->gr_name, grp->gr_name, len);
+               new->gr_name[len] = '\0';
+               
+               len = strlen(grp->gr_passwd);
+               if((new->gr_passwd= (char *)malloc(len+1)) == NULL) {
+                       log(L_ERR, "HASH:  (buildGrplist) Out of memory!");
+                       return -1;
+               }
+               strncpy(new->gr_passwd, grp->gr_passwd, len);
+               new->gr_passwd[len] = '\0';
+
+               new->gr_gid = grp->gr_gid;      
+               
+               /* Allocate space for user list, as much as I hate doing groups
+                * that way.  
+                */
+               for(member = grp->gr_mem; *member!=NULL; member++);
+               len = member - grp->gr_mem;
+               if((new->gr_mem = (char **)malloc((len+1)*sizeof(char **))) == NULL) {
+                       log(L_ERR, "HASH:  (buildGrplist) Out of memory!");
+                       return -1;
+               }
+               /* Now go back and copy individual users into it */
+               for(member = grp->gr_mem; *member; member++) {
+                       len2 = strlen(*member);
+                       index = member - grp->gr_mem;
+                       if((new->gr_mem[index] = (char *)malloc(len2+1)) == NULL) {
+                               log(L_ERR, "HASH:  (buildGrplist) Out of memory!");
+                               return -1;
+                       }
+                       strncpy(new->gr_mem[index], *member, len2);
+                       new->gr_mem[index][len2] = '\0';
+               }
+               /* Make sure last entry in user list is 0 so we can loop thru it */
+               new->gr_mem[len] = 0;
+
+               /* Insert at beginning of list */
+               new->next = grphead;
+               grphead = new;
+
+               numread++;
+       }
+
+       /* End */
+       endgrent();
+
+       log(L_INFO, "HASH:  Stored %d entries from /etc/group", numread);
+
+       return 0;
+}
+
+/* This function changes the loggedin variable for a user
+ * when they login or out.  This lets us keep track of 
+ * what radutmp is doing without having to read it
+ */
+void chgLoggedin(char *user, int diff) {
+       struct mypasswd *cur;
+
+       cur = findHashUser(user);
+       if(cur) {
+               cur->loggedin += diff;
+               /* Can't have less than 0 logins */
+               if(cur->loggedin<0) {
+                       cur->loggedin = 0;
+               }
+               DEBUG2("  HASH:  Changed user %s to %d logins", user, cur->loggedin);
+       }
+}
+
+/*
+ * Looks up user in hashtable.  If user can't be found, returns 0.  
+ * Otherwise returns a pointer to the structure for the user
+ */
+struct mypasswd *findHashUser(const char *user) {
+
+       struct mypasswd *cur;
+       int index;
+
+       /* first hash the username and get the index into the hashtable */
+       index = hashUserName(user);
+
+       cur = hashtable[index];
+
+       while((cur != NULL) && (strcmp(cur->pw_name, user))) {
+               cur = cur->next;
+       }
+
+       if(cur) {
+               DEBUG2("  HASH:  user %s found in hashtable bucket %d", user, index);
+               return cur;
+       }
+
+       return (struct mypasswd *)0;
+
+}
+
+/* Stores the username sent into the hashtable */
+int storeHashUser(struct mypasswd *new, int index) {
+
+       /* store new record at beginning of list */
+       new->next = hashtable[index];
+       hashtable[index] = new;
+
+       return 1;
+}
+
+/* Hashes the username sent to it and returns index into hashtable */
+int hashUserName(const char *s) {
+     unsigned long hash = 0;
+
+     while (*s != '\0') {
+         hash = hash * 7907 + (unsigned char)*s++;
+               }
+
+     return (hash % HASHTABLESIZE);
+}              
+
+/* Reads radutmp file, and increments the loggedin variable
+ * for every login a user has...assuming we can find the user
+ * in the hashtable
+ */
+int hashradutmp(void) {
+
+       int fd;
+       struct radutmp u;
+       struct mypasswd *cur;
+
+   if ((fd = open(RADUTMP, O_CREAT|O_RDONLY, 0644)) < 0)
+      return 0;
+
+   while(read(fd, &u, sizeof(u)) == sizeof(u)) {
+      if ((u.login) && (u.type == P_LOGIN)) {
+                       cur = findHashUser(u.login);
+                       if(cur) {
+                               cur->loggedin++;                
+                       }
+               }
+       }
+       close(fd);
+
+       return 1;
+}
+
+/*
+ *     Emulate the cistron unix_pass function, but do it using 
+ *     our hashtable (iow, make it blaze).
+ * return  0 on success
+ * return -1 on failure
+ * return -2 on error (let caller fall back to old method)
+ */
+int H_unix_pass(char *name, char *passwd) {
+       struct mypasswd *pwd;
+       char *encrypted_pass;
+       char *encpw;
+
+       /*
+        *      Get encrypted password from password file
+        */
+       if ((pwd = findHashUser(name)) == NULL) {
+               /* Default to old way if user isn't hashed */
+               return -2;
+       }
+       encrypted_pass = pwd->pw_passwd;
+
+       /*
+        *      We might have a passwordless account.
+        */
+       if (encrypted_pass[0] == 0) return 0;
+
+       /*
+        *      Check encrypted password.
+        */
+       encpw = (char *)crypt(passwd, encrypted_pass);
+       if (strcmp(encpw, encrypted_pass))
+               return -1;
+
+       return 0;
+}
+
+/*
+ * Emulate groupcmp in files.c, but do it (much) faster
+ * return -2 on error (let caller fall back to old method),
+ * -1 on match fail, or 0 on success
+ */
+int H_groupcmp(VALUE_PAIR *check, char *username) {
+       struct mypasswd *pwd;
+       struct mygroup *cur;
+       char **member;
+
+       /* get the user from the hash */
+       if (!(pwd = findHashUser(username)))
+               return -2;
+
+       /* let's find this group */
+       if(grphead) {
+               cur = grphead;
+               while((cur) && (strcmp(cur->gr_name, check->strvalue))) {
+                       cur = cur->next;        
+               }       
+               /* found the group, now compare it */
+               if(!cur) {
+                       /* Default to old function if we can't find it */
+                       return -2;
+               } else {
+                       if(pwd->pw_gid == cur->gr_gid) {
+                               DEBUG2("  HASH:  matched user %s in group %s", username, cur->gr_name);
+                               return 0;
+                       } else {
+                               for(member = cur->gr_mem; *member; member++) {
+                                       if (strcmp(*member, pwd->pw_name) == 0) {
+                                               DEBUG2("  HASH:  matched user %s in group %s", username, cur->gr_name);
+                                               return 0;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       return -1;
+}
diff --git a/src/modules/rlm_unix/cache.h b/src/modules/rlm_unix/cache.h
new file mode 100644 (file)
index 0000000..2b99a13
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * cache.h   Definitions for structures and functions needed in cache.c
+ *
+ * Version: cache.c  0.99  04-13-1999  jeff@apex.net
+ */    
+#ifndef _CACHE_H
+#define _CACHE_H
+
+/* Misc definitions */
+#define BUFSIZE  1024
+#define MAXUSERNAME 20
+#define HASHTABLESIZE 100000
+#define PASSWDFILE "/etc/passwd"
+#define SHADOWFILE "/etc/shadow"
+#endif
+
+/* Structure definitions */
+struct mypasswd {
+       char    *pw_name;       /* user name */
+       char    *pw_passwd;     /* user password */
+       uid_t   pw_uid;         /* user id */
+       gid_t   pw_gid;         /* group id */
+       int     loggedin;       /* number of logins */
+       struct mypasswd *next;  /* next */
+};
+
+struct mygroup {
+       char    *gr_name;        /* group name */
+       char    *gr_passwd;      /* group password */
+       gid_t   gr_gid;          /* group id */
+       char    **gr_mem;        /* group members */
+       struct mygroup *next;    /* next */
+};         
+
+/* Function prototypes */
+int buildHashTable(void);
+int buildGrpList(void);
+void chgLoggedin(char *user, int diff);
+struct mypasswd *findHashUser(const char *user);
+int storeHashUser(struct mypasswd *new, int index);
+int hashUserName(const char *s);
+int hashradutmp(void);
+int H_unix_pass(char *name, char *passwd);
+int H_groupcmp(VALUE_PAIR *check, char *username);
diff --git a/src/modules/rlm_unix/config.h b/src/modules/rlm_unix/config.h
new file mode 100644 (file)
index 0000000..c81be5a
--- /dev/null
@@ -0,0 +1,6 @@
+#define HAVE_CRYPT_H 1
+#define LIBCRYPT 1
+#define HAVE_GETSPNAM 1
+#define ETC_SHADOW "/etc/shadow"
+#define HAVE_SHADOW_H 1
+#define HAVE_GETUSERSHELL 1
diff --git a/src/modules/rlm_unix/config.mak b/src/modules/rlm_unix/config.mak
new file mode 100644 (file)
index 0000000..68a1429
--- /dev/null
@@ -0,0 +1,6 @@
+HAVE_CRYPT_H=
+LIBCRYPT=-lcrypt
+HAVE_GETSPNAM=
+ETC_SHADOW=/etc/shadow
+HAVE_SHADOW_H=
+HAVE_GETUSERSHELL=
diff --git a/src/modules/rlm_unix/rlm_unix.c b/src/modules/rlm_unix/rlm_unix.c
new file mode 100644 (file)
index 0000000..f2d93b7
--- /dev/null
@@ -0,0 +1,458 @@
+/*
+ * rlm_unix.c  authentication: Unix user authentication
+ *             accounting:     Functions to write radwtmp file.
+ *             Also contains handler for "Group".
+ *
+ * Version:    @(#)rlm_unix.c  1.00  08-Aug-1999  miquels@cistron.nl
+ *
+ */
+char rlm_unix_sccsid[] =
+"@(#)rlm_unix.c        1.00 Copyright 1998-1999 Cistron Internet Services B.V.";
+
+#include       "autoconf.h"
+
+#include       <sys/types.h>
+#include       <sys/time.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <string.h>
+#include       <time.h>
+#include       <unistd.h>
+#include       <grp.h>
+#include       <pwd.h>
+#include       <errno.h>
+
+#include "config.h"
+
+#if HAVE_MALLOC_H
+#  include <malloc.h>
+#endif
+
+#if HAVE_SHADOW_H
+#  include     <shadow.h>
+#endif
+
+#if HAVE_CRYPT_H
+#  include <crypt.h>
+#endif
+
+#ifdef OSFC2
+#  include     <sys/security.h>
+#  include     <prot.h>
+#endif
+
+#include       "radiusd.h"
+#include       "modules.h"
+#include       "sysutmp.h"
+#include       "cache.h"
+
+#if !HAVE_CRYPT_H
+  extern char *crypt();
+#endif
+
+static char trans[64] =
+   "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+#define ENC(c) trans[c]
+
+/*
+ *     The Group = handler.
+ */
+static int groupcmp(VALUE_PAIR *request, VALUE_PAIR *check,
+       VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
+{
+       struct passwd   *pwd;
+       struct group    *grp;
+       char            **member;
+       char            *username;
+       int             retval;
+
+       username = request->strvalue;
+
+       if (cache_passwd && (retval = H_groupcmp(check, username)) != -2)
+               return retval;
+
+       if ((pwd = rad_getpwnam(username)) == NULL)
+               return -1;
+
+       if ((grp = getgrnam(check->strvalue)) == NULL)
+               return -1;
+
+       retval = (pwd->pw_gid == grp->gr_gid) ? 0 : -1;
+       if (retval < 0) {
+               for (member = grp->gr_mem; *member && retval; member++) {
+                       if (strcmp(*member, pwd->pw_name) == 0)
+                               retval = 0;
+               }
+       }
+       return retval;
+}
+
+
+/*
+ *     FIXME:  We really should have an 'init' which makes
+ *     System auth == Unix
+ */
+static int unix_init(int argc, char **argv)
+{
+       paircompare_register(PW_GROUP, PW_USER_NAME, groupcmp);
+#ifdef PW_GROUP_NAME /* compat */
+       paircompare_register(PW_GROUP_NAME, PW_USER_NAME, groupcmp);
+#endif
+       if (cache_passwd) {
+               log(L_INFO, "HASH:  Reinitializing hash structures "
+                       "and lists for caching...");
+               if(buildHashTable() < 0) {
+                       log(L_ERR, "HASH:  unable to create user "
+                               "hash table.  disable caching and run debugs");
+                       return -1;
+               }
+               if (buildGrpList() < 0) {
+                       log(L_ERR, "HASH:  unable to cache groups file.  "
+                               "disable caching and run debugs");
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+
+/*
+ *     Detach.
+ */
+static int unix_detach(void)
+{
+       paircompare_unregister(PW_GROUP, groupcmp);
+#ifdef PW_GROUP_NAME
+       paircompare_unregister(PW_GROUP_NAME, groupcmp);
+#endif
+       return 0;
+}
+
+
+/*
+ *     Check the users password against the standard UNIX
+ *     password table.
+ */
+static int unix_authenticate(REQUEST *request, char *name, char *passwd)
+{
+       struct passwd   *pwd;
+       char            *encpw;
+       char            *encrypted_pass;
+       int             ret;
+#if HAVE_GETSPNAM
+#if defined(M_UNIX)
+       struct passwd   *spwd;
+#else
+       struct spwd     *spwd;
+#endif
+#endif
+#ifdef OSFC2
+       struct pr_passwd *pr_pw;
+#endif
+#ifdef HAVE_GETUSERSHELL
+       char            *shell;
+#endif
+
+       if (cache_passwd && (ret = H_unix_pass(name, passwd)) != -2)
+               return (ret == 0) ? RLM_AUTH_OK : RLM_AUTH_REJECT;
+
+#ifdef OSFC2
+       if ((pr_pw = getprpwnam(name)) == NULL)
+               return -1;
+       encrypted_pass = pr_pw->ufld.fd_encrypt;
+#else /* OSFC2 */
+       /*
+        *      Get encrypted password from password file
+        */
+       if ((pwd = rad_getpwnam(name)) == NULL) {
+               return RLM_AUTH_REJECT;
+       }
+       encrypted_pass = pwd->pw_passwd;
+#endif /* OSFC2 */
+
+#if HAVE_GETSPNAM
+       /*
+        *      See if there is a shadow password.
+        */
+       if ((spwd = getspnam(name)) != NULL)
+#if defined(M_UNIX)
+               encrypted_pass = spwd->pw_passwd;
+#else
+               encrypted_pass = spwd->sp_pwdp;
+#endif /* M_UNIX */
+#endif /* HAVE_GETSPNAM */
+
+#ifdef DENY_SHELL
+       /*
+        *      Undocumented temporary compatibility for iphil.NET
+        *      Users with a certain shell are always denied access.
+        */
+       if (strcmp(pwd->pw_shell, DENY_SHELL) == 0) {
+               log(L_AUTH, "rlm_unix: [%s]: invalid shell", name);
+               return RLM_AUTH_REJECT;
+       }
+#endif
+
+#if HAVE_GETUSERSHELL
+       /*
+        *      Check /etc/shells for a valid shell. If that file
+        *      contains /RADIUSD/ANY/SHELL then any shell will do.
+        */
+       while ((shell = getusershell()) != NULL) {
+               if (strcmp(shell, pwd->pw_shell) == 0 ||
+                   strcmp(shell, "/RADIUSD/ANY/SHELL") == 0) {
+                       break;
+               }
+       }
+       endusershell();
+       if (shell == NULL)
+               return RLM_AUTH_REJECT;
+#endif
+
+#if defined(HAVE_GETSPNAM) && !defined(M_UNIX)
+       /*
+        *      Check if password has expired.
+        */
+       if (spwd && spwd->sp_expire > 0 &&
+           (time(NULL) / 86400) > spwd->sp_expire) {
+               log(L_AUTH, "rlm_unix: [%s]: password has expired", name);
+               return RLM_AUTH_REJECT;
+       }
+#endif
+
+#if defined(__FreeBSD__) || defined(bsdi) || defined(_PWF_EXPIRE)
+       /*
+        *      Check if password has expired.
+        */
+       if (pwd->pw_expire > 0 && time(NULL) > pwd->pw_expire) {
+               log(L_AUTH, "rlm_unix: [%s]: password has expired", name);
+               return RLM_AUTH_REJECT;
+       }
+#endif
+
+#ifdef OSFC2
+       /*
+        *      Check if account is locked.
+        */
+       if (pr_pw->uflg.fg_lock!=1) {
+               log(L_AUTH, "rlm_unix: [%s]: account locked", name);
+               return RLM_AUTH_REJECT;
+       }
+#endif /* OSFC2 */
+
+       /*
+        *      We might have a passwordless account.
+        */
+       if (encrypted_pass[0] == 0)
+               return RLM_AUTH_OK;
+
+       /*
+        *      Check encrypted password.
+        */
+       encpw = crypt(passwd, encrypted_pass);
+       if (strcmp(encpw, encrypted_pass))
+               return RLM_AUTH_REJECT;
+
+       return RLM_AUTH_OK;
+}
+
+/*
+ *     UUencode 4 bits base64. We use this to turn a 4 byte field
+ *     (an IP adres) into 6 bytes of ASCII. This is used for the
+ *     wtmp file if we didn't find a short name in the naslist file.
+ */
+static char *uue(void *in)
+{
+       int i;
+       static unsigned char res[7];
+       unsigned char *data = (char *)in;
+
+       res[0] = ENC( data[0] >> 2 );
+       res[1] = ENC( ((data[0] << 4) & 060) + ((data[1] >> 4) & 017) );
+       res[2] = ENC( ((data[1] << 2) & 074) + ((data[2] >> 6) & 03) );
+       res[3] = ENC( data[2] & 077 );
+
+       res[4] = ENC( data[3] >> 2 );
+       res[5] = ENC( (data[3] << 4) & 060 );
+       res[6] = 0;
+
+       for(i = 0; i < 6; i++) {
+               if (res[i] == ' ') res[i] = '`';
+               if (res[i] < 32 || res[i] > 127)
+                       printf("uue: protocol error ?!\n");
+       }
+       return res;
+}
+
+
+/*
+ *     Unix accounting - write a wtmp file.
+ */
+static int unix_accounting(REQUEST *request)
+{
+       VALUE_PAIR      *vp;
+       NAS             *cl;
+       FILE            *fp;
+       struct utmp     ut;
+       time_t          t;
+       char            buf[64];
+       char            *s;
+       int             delay = 0;
+       int             status = -1;
+       int             nas_address = 0;
+       int             framed_address = 0;
+       int             protocol = -1;
+       int             nas_port = 0;
+       int             port_seen = 0;
+       int             nas_port_type = 0;
+
+       /*
+        *      Which type is this.
+        */
+       if ((vp = pairfind(request->packet->vps, PW_ACCT_STATUS_TYPE))==NULL) {
+               log(L_ERR, "Accounting: no Accounting-Status-Type record.");
+               return RLM_ACCT_FAIL_SOFT;
+       }
+       status = vp->lvalue;
+
+       /*
+        *      FIXME: handle PW_STATUS_ALIVE like 1.5.4.3 did.
+        */
+       if (status != PW_STATUS_START &&
+           status != PW_STATUS_STOP)
+               return RLM_ACCT_OK;
+
+       /*
+        *      We're only interested in accounting messages
+        *      with a username in it.
+        */
+       if ((vp = pairfind(request->packet->vps, PW_USER_NAME)) == NULL)
+               return RLM_ACCT_OK;
+
+       time(&t);
+       memset(&ut, 0, sizeof(ut));
+
+       /*
+        *      First, find the interesting attributes.
+        */
+       for (vp = request->packet->vps; vp; vp = vp->next) {
+               switch (vp->attribute) {
+                       case PW_USER_NAME:
+                               strncpy(ut.ut_name, vp->strvalue, UT_NAMESIZE);
+                               break;
+                       case PW_LOGIN_IP_HOST:
+                       case PW_FRAMED_IP_ADDRESS:
+                               framed_address = vp->lvalue;
+                               break;
+                       case PW_FRAMED_PROTOCOL:
+                               protocol = vp->lvalue;
+                               break;
+                       case PW_NAS_IP_ADDRESS:
+                               nas_address = vp->lvalue;
+                               break;
+                       case PW_NAS_PORT_ID:
+                               nas_port = vp->lvalue;
+                               port_seen = 1;
+                               break;
+                       case PW_ACCT_DELAY_TIME:
+                               delay = vp->lvalue;
+                               break;
+                       case PW_NAS_PORT_TYPE:
+                               nas_port_type = vp->lvalue;
+                               break;
+               }
+       }
+
+       /*
+        *      We don't store !root sessions, or sessions
+        *      where we didn't see a PW_NAS_PORT_ID.
+        */
+       if (strncmp(ut.ut_name, "!root", sizeof(ut.ut_name)) == 0 || !port_seen)
+               return RLM_ACCT_OK;
+
+       /*
+        *      If we didn't find out the NAS address, use the
+        *      originator's IP address.
+        */
+       if (nas_address == 0)
+               nas_address = request->packet->src_ipaddr;
+
+#ifdef __linux__
+       /*
+        *      Linux has a field for the client address.
+        */
+       ut.ut_addr = framed_address;
+#endif
+       /*
+        *      We use the tty field to store the terminal servers' port
+        *      and address so that the tty field is unique.
+        */
+       s = "";
+       if ((cl = nas_find(nas_address)) != NULL)
+               s = cl->shortname;
+       if (s == NULL || s[0] == 0) s = uue(&(nas_address));
+#if UT_LINESIZE > 9
+       sprintf(buf, "%03d:%s", nas_port, s);
+#else
+       sprintf(buf, "%02d%s", nas_port, s);
+#endif
+       strncpy(ut.ut_line, buf, UT_LINESIZE);
+
+       /*
+        *      We store the dynamic IP address in the hostname field.
+        */
+#ifdef UT_HOSTSIZE
+       if (framed_address) {
+               ip_ntoa(buf, framed_address);
+               strncpy(ut.ut_host, buf, UT_HOSTSIZE);
+       }
+#endif
+#ifdef __svr4__
+       ut.ut_xtime = t- delay;
+#else
+       ut.ut_time = t - delay;
+#endif
+#ifdef USER_PROCESS
+       /*
+        *      And we can use the ID field to store
+        *      the protocol.
+        */
+       if (protocol == PW_PPP)
+               strcpy(ut.ut_id, "P");
+       else if (protocol == PW_SLIP)
+               strcpy(ut.ut_id, "S");
+       else
+               strcpy(ut.ut_id, "T");
+       ut.ut_type = status == PW_STATUS_STOP ? DEAD_PROCESS : USER_PROCESS;
+#endif
+       if (status == PW_STATUS_STOP)
+               ut.ut_name[0] = 0;
+
+       /*
+        *      Write a RADIUS wtmp log file.
+        *      FIXME: return correct error.
+        *      Check if file is there. If not, we don't write the
+        *      wtmp file. If it is, we try to write. If we fail,
+        *      return RLM_ACCT_FAIL ..
+        */
+       if ((fp = fopen(RADWTMP, "a")) != NULL) {
+               fwrite(&ut, sizeof(ut), 1, fp);
+               fclose(fp);
+       }
+
+       return RLM_ACCT_OK;
+}
+
+/* globally exported name */
+module_t rlm_unix = {
+  "System",
+  0,                            /* type: reserved */
+  unix_init,                    /* initialization */
+  NULL,                         /* authorization */
+  unix_authenticate,            /* authentication */
+  unix_accounting,              /* accounting */
+  unix_detach,                  /* detach */
+};
+
diff --git a/src/modules/rules.mak b/src/modules/rules.mak
new file mode 100644 (file)
index 0000000..b7c52b8
--- /dev/null
@@ -0,0 +1,88 @@
+#######################################################################
+#
+#  Each module should have a few common defines at the TOP of the
+# Makefile, and the 'include ../rules.mak'
+#
+# e.g.
+#
+##########################
+# TARGET = rlm_foo
+# SRCS   = rlm_foo.c other.c
+#
+# include ../rules.mak
+#
+# CFLAGS += my_c_flags
+##########################
+#
+# and everything will be automagically built
+#
+#######################################################################
+
+include ../../../Make.inc
+
+all: static dynamic
+
+#######################################################################
+#
+#  definitions for new dependencies on suffixes
+#
+#######################################################################
+.SUFFIXES: .lo .o .so .a
+
+#######################################################################
+#
+# define static and dynamic objects for the libraries
+#
+#######################################################################
+STATIC_OBJS    = $(SRCS:.c=.o)
+DYNAMIC_OBJS   = $(SRCS:.c=.lo)
+
+#######################################################################
+#
+# define new rules
+#
+#######################################################################
+%.o : %.c
+       $(CC) $(CFLAGS) -c $< -o $@
+
+%.lo : %.c
+       $(CC) $(CFLAGS) -fPIC -c $< -o $@
+
+CFLAGS         += -I../../include
+
+#######################################################################
+#
+# Define a number of new targets
+#
+#######################################################################
+$(TARGET).a: $(STATIC_OBJS)
+       $(AR) crv $@ $^
+
+$(TARGET).so: $(DYNAMIC_OBJS)
+       $(CC) $(CFLAGS) $(LIBS) -shared $^ -o $@
+
+#######################################################################
+#
+#  Generic targets so we can sweep through all modules
+# without knowing what their names are.
+#
+#  These rules also allow us to copy the '.a' or '.so' up
+# a level, to the 'src/modules' directory, for general consumption.
+#
+#######################################################################
+static: $(TARGET).a
+       @cp $< ..
+
+dynamic: $(TARGET).so
+       @cp $< ..
+
+#######################################################################
+#
+#  clean and install rules
+#
+#######################################################################
+clean:
+       @rm -f *.a *.o *.lo *.so *~
+
+reallyclean: clean
+       @rm -f config.h config.mak
diff --git a/todo/TODO b/todo/TODO
new file mode 100644 (file)
index 0000000..353843f
--- /dev/null
+++ b/todo/TODO
@@ -0,0 +1,56 @@
+INTEGRATE FROM ALAN:
+
+o operator support in pairmove. Actually should make 2 pairmove's,
+  one for the authorize stuff in src/valuepair.c, and another generic
+  one in lib/valuepair.c that does what the name implies.
+
+URGENT:
+
+o Prefix/Suffix in users file isn't stripped anymore at the
+  accounting stage.
+o UPDATE accounting requests aren't handled as in 1.5.4.3 for wtmp
+  Is this a problem ? Need to fix in rlm_unix.c
+
+MEDIUM PRIORITY:
+o Provide a way to define the locations of all files (/etc/raddb/radiusd.conf?)
+  - this will be the newstyle radius configuration file
+
+LOW PRIORITY:
+o Write better documentation
+o Manual pages for the daemon, utilities and conffiles (some done)
+o Fix all FIXME's in the source.
+o Fix DBM support:
+  - Multiple defaults (done)
+  - Fallthrough (hard for not DEFAULT entries)
+o there should be a way that radius itself could
+  rotate the wtmp file properly. It should write "logout" records for
+  all users, move the file to wtmp.0, and create a new wtmp file with
+  "login" records for all currently online users.
+
+DONE:
+o Radius proxy support.
+o Max-Simultaneous-Use parameter to avoid double logins.
+o Specify a program to be run on succesful login
+o Prefix/Suffix support
+o Change radutmp format to v2 (see radutmp.h)
+o move radutmp to /var/log ?
+o Compatibility with radius-2.0
+o Support for pidfile
+o Configurable logging: both radutmp/radwtmp and details files
+o session_id is not numeric but an 8-byte (?) string !
+o Detect reboot packet sent by portmaster and clear radutmp / wtmp
+o Seperate /etc/raddb/clients into public and private file (secret == secret!)
+  Add ts-type field to clients file for checklogin.pl
+  Better: return clients to old form (no shortname) and add a new file,
+  "nas" or so. Matching on this file is done based on Nas-Ip-Address
+  instead of the IP address of the sender. Better if there's a proxy
+  in between.
+o Allow spaces in usernames (using " or \ to escape)
+o Return Proxy-State A/V pairs, in the right order.
+o retransmits from the terminal server get proxied with
+  a new ID and random_vector. We should check for this!
+o Limit logins based on time/date 
+  (for example, Login-Hour = 8-18, Login-Day = 0-5 for business hours)
+o take out host-order IP addresses
+o Support Connect-Rate
+
diff --git a/todo/proposed-new-users b/todo/proposed-new-users
new file mode 100644 (file)
index 0000000..c87b1fa
--- /dev/null
@@ -0,0 +1,57 @@
+
+Adding new features usually requires adding yet another
+file. We already have a slwe of files in /etc/raddb, it should be
+possible to fold them into one. From radiusd's point of view that
+is, by using $INCLUDE statements it would still be possible for
+the admin to concentrate different things (like huntgroups) in
+a seperate file.
+
+Hints could be done with:
+
+user * {
+       check:          Prefix = "U"
+       transform:      Strip-User-Name = Yes
+       check-add:      Hint = "PPP",
+                       Service-Type = Framed-User,
+                       Framed-Protocol = PPP
+}
+
+Huntgroups with:
+
+user * {
+       check:          NAS-IP-Address = 192.168.2.5
+       check:          NAS-IP-Address = 192.168.2.6
+       check:          NAS-IP-Address = 192.168.2.7
+       auth:           Group = "staff"
+       auth:           Group = "cistron"
+       check-add:      Huntgroup = alphen
+}
+
+Normal entry, but with CLID auth instead of passwd
+
+username remoterouter {
+       check:          Service-Type = Framed-User
+       auth:           Calling-Station-Id = "55512345"
+       reply:          Framed-IP-Address = 192.168.1.2,
+                       Service-Type = Framed-User,
+                       Framed-Protocol = PPP
+       exec-program:   /usr/local/bin/loggedin
+       fallthrough:    no
+}
+
+Basically the keywords should be:
+
+check:         all items must match
+               Multiple check statements can be present which
+               will be ORed (entry applkies when one matches)
+               If entry doesn't match, the next entry will be tried
+auth:          If check matches, authentication will be done.
+               If authentication fails we don't fall through ever
+reply:         Set the reply message to something
+reply-add:     Add something to the existing reply-message
+check-add:     Add something to the existing check pairs
+fallthrough:   Fall through to the next entry (unless auth failed)
+transform:     rules to change the username. Not quite sure how
+               to do this yet.
+stage:         (auth|acct) to apply at authentication or accounting time
+
diff --git a/todo/radius.conf.sample2 b/todo/radius.conf.sample2
new file mode 100644 (file)
index 0000000..b25469a
--- /dev/null
@@ -0,0 +1,45 @@
+
+confdir:               /etc/raddb
+authlog:               /var/log/radius.log
+acctlog:               /var/log/radacct/%s/detail
+radwtmp:               /var/log/radwtmp
+radutmp:               /var/log/radutmp
+pidfile:               /var/run/radiusd.pid
+checkrad:              /usr/local/sbin/checkrad
+
+avgroup common {
+   auth-recv-allow:    Framed-MTU
+   auth-recv-allow:    Idle-Timeout
+   auth-recv-allow:    Reply-Message
+   auth-recv-allow:    Filter-Id
+   auth-recv-allow:    Port-Limit
+   auth-recv-allow:    Session-Timeout
+   auth-recv-allow:    Idle-Timeout
+   auth-recv-allow:    Framed-Protocol
+   auth-recv-allow:    Framed-Compression
+   auth-recv-allow:    Service-Type = Login-User
+   auth-recv-allow:    Login-Service
+   auth-recv-allow:    Login-IP-Host
+}
+
+proxy domain.com {
+   authproxy:          pr1.domain.com:1645
+   acctproxy:          pr1.domain.com:1646
+   auth-send-allow:    A/V pairs
+   auth-send-deny:     ALL
+   auth-recv-allow:    Framed-Address = 192.168.1.2/26
+   auth-recv-allow:    Framed-Netmask = 255.255.255.255/26
+   auth-recv-allow:    common
+   auth-recv-deny:     ALL
+   acct-send-deny:     Caller-ID
+   acct-send-allow:    ALL
+   authlog:            /var/log/radius.pr1.log
+   acctlog:            /var/log/radacct/pr1/detail
+}
+
+nas 192.168.1.1 {
+   shortname:          cs-1.alp
+   type:               livingston
+}
+
+
diff --git a/todo/realm.c b/todo/realm.c
new file mode 100644 (file)
index 0000000..f33e0a3
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * realm.c     Read and process realm file.
+ *
+ *
+ * Version:    @(#)  realm.c  16-Jul-1998  miquels@cistron.nl
+ *
+ */
+
+char util_sccsid[] =
+"@(#)realm.c   1.0 Copyright 1998 Cistron Internet Services B.V.";
+
+#include       <sys/types.h>
+#include       <sys/socket.h>
+#include       <sys/time.h>
+#include       <netinet/in.h>
+
+#include       <stdio.h>
+#include       <stdlib.h>
+#include       <netdb.h>
+#include       <pwd.h>
+#include       <time.h>
+#include       <ctype.h>
+
+#include       "radiusd.h"
+
+CONF *conf;
+
+struct tpl {
+       char    *name;
+       int     offset;
+};
+
+static struct tpl tpl[] = {
+  {  "realm",          offsetof(CONF, realm)           },
+  {  "radwtmp",        offsetof(CONF, radwtmp)         },
+  {  "radutmp",        offsetof(CONF, radutmp)         },
+  {  "acctdir",        offsetof(CONF, acctdir)         },
+  {  "acctdir2",       offsetof(CONF, acctdir2)        },
+  {  "authproxy",      offsetof(CONF, authproxy)       },
+  {  "acctproxy",      offsetof(CONF, acctproxy)       },
+  {  "striprealm",     offsetof(CONF, striprealm)      },
+  {  NULL,             -1                              },
+};
+
+/*
+ *     Initialize the config file structs.
+ */
+static CONF *initconf(void)
+{
+       conf = (CONF *)malloc(sizeof(CONF));
+       memset(conf, 0, sizeof(CONF));
+
+       strcpy(conf->radutmp, RADUTMP);
+       strcpy(conf->radutmp, RADWTMP);
+       strcpy(conf->confdir, RADIUS_DIR);
+       strcpy(conf->acctdir, RADACCT_DIR);
+       strcpy(conf->logdir, RADLOG_DIR);
+       strcpy(conf->pidfile, RADIUS_PID);
+       strcpy(conf->checkrad,  CHECKRAD1);
+       strcpy(conf->checkrad2, CHECKRAD2);
+       strcpy(conf->striprealm, "yes");
+
+       return conf;
+}
+
+/*
+ *     Read the config file.
+ */
+int readconf(char *conffile)
+{
+       FILE    *fp;
+       char    buf[128];
+       char    *key, *val;
+       char    lineno = 0;
+       CONF    *cf, *cf2;
+       int     first = 1;
+
+       /*
+        *      Initialize.
+        */
+       if ((fp = fopen(conffile, "r")) == NULL) {
+               log(L_ERR, "%s: %s", conffile, strerror(errno));
+               return -1;
+       }
+       cf = initconf();
+
+       /*
+        *      Read config file line by line.
+        */
+       while(fgets(buf, sizeof(buf), fp)) {
+               lineno++;
+               /*
+                *      Skip comments and empty lines, and split
+                *      the rest up in key/value pairs.
+                */
+               if (buf[0] == '#' || buf[0] == '\n' || buf[0] == 0)
+                       continue;
+               key = strtok(buf, " \t");
+               val = strtok(NULL, "\n");
+               if (key == NULL || key[0] == 0 ||
+                   val == NULL || val[0] == 0) {
+                       log(L_ERR, "%s[%d]: syntax error", conffile, lineno);
+                       return -1;
+               }
+
+               /*
+                *      The "realm" key is special, we allocate a new
+                *      CONF now _unless_ the "realm" keyword is the
+                *      first keyword in the file.
+                */
+               if (strcmp(key, "realm") == 0 && !first) {
+                       cf2 = (CONF *)malloc(sizeof(CONF));
+                       memcpy(cf2, cf, sizeof(CONF));
+                       strcpy(cf2->striprealm, "no");
+                       cf->next = cf2;
+                       cf = cf2;
+               }
+               first = 0;
+
+               /*
+                *      Find the key in our keyword list and
+                *      calculate the offset into the CONF struct
+                *      for the value.
+                */
+               for(i = 0; tpl[i].name; i++) {
+                       if (strcmp(tpl[i].name, key) == 0)
+                               break;
+               }
+               if (tpl[i].name == NULL) {
+                       log(L_ERR, "%s[%d]: unknown keyword %s",
+                               conffile, lineno, key);
+                       return -1;
+               }
+               strcpy((char *)cf + tpl[i].offset, val);
+       }
+       fclose (fp);
+
+       return 0;
+}
+
+/*
+ *     Find the configuration for a certain realm.
+ *     We modify the username in-place, so this function should
+ *     only be called once.
+ */
+CONF *getconf(char *username)
+{
+       char    buf[128];
+       char    *realm, *user;
+       CONF    *cf;
+
+       strncpy(buf, username, 128);
+       buf[128] = 0;
+
+       /*
+        *      Split username and realm. We support both
+        *      realm\username and username@realm.
+        */
+       if ((realm = strchr(buf, '@')) != NULL) {
+               *realm++ = 0;
+               user = buf;
+       } else if ((user = strchr(buf, '\\')) != NULL) {
+               *user++ = 0;
+               realm = buf;
+       } else
+               return conf;
+
+       /*
+        *      Find this realm in the conffile, if not found use
+        *      the default (local) realm and do not strip the realm,
+        *      If found strip realm from username if needed.
+        */
+       for (cf = conf; cf; cf = cf->next)
+               if (strcasecmp(realm, cf->realm) == 0)
+                       break;
+       if (cf == NULL) {
+               cf = conf;
+       } else {
+               if (strcmp(cf->striprealm, "yes") == 0)
+                       strcpy(username, user);
+       }
+
+       return conf;
+}
+
diff --git a/todo/realm.h b/todo/realm.h
new file mode 100644 (file)
index 0000000..a1da547
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *     Yep, this struct is too big, using fixed length strings
+ *     is evil. But it makes things easier - for now.
+ */
+typedef struct conf {
+       char                    realm[128];
+       char                    radwtmp[128];
+       char                    radutmp[128];
+       char                    acctdir[128];
+       char                    acctdir2[128];
+       char                    authproxy[128];
+       char                    acctproxy[128];
+       char                    striprealm[128];
+       struct conf             *next;
+} CONF;
+
diff --git a/todo/realms b/todo/realms
new file mode 100644 (file)
index 0000000..9abc612
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# realms       Realm-specific definitions.
+#              A realm is the part after an `@' sign in a loginname.
+#
+
+#
+#      The first few entries are global settings.
+#
+#      Notes:  you can define acctdir and acctdir2, and in both
+#              directories the detail log will be written. `%s' expands
+#              to the (short) name of the terminal server.
+#
+radwtmp                /var/log/radwtmp
+radutmp                /var/log/radutmp
+acctdir                /var/log/radacct/%s
+
+#
+#      All entries can be overridden on a per-realm base. Specific
+#      entries for a realm are:
+#
+#      authproxy:      remote_radius[:port]  secret
+#      acctproxy:      remote_radius[:port]  secret
+#
+realm example.nl
+acctdir                /var/log/radacct/%s
+acctdir2       /var/log/radacct/example
+authproxy      radius.example.nl       testing123
+acctproxy      radius.example.nl       testing123
+
+realm voorbeeld.nl
+acctdir                /var/log/radacct/%s
+acctdir2       /var/log/radacct/voorbeeld
+authproxy      radius.voorbeeld.nl:1812        HellOtHere
+acctproxy      radius.voorbeeld.nl:1813        HellOtHere
+