--- /dev/null
+
+ 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.
+
--- /dev/null
+
+Please read the README in the doc/ subdirectory. Paragraph 2 tells
+you how to configure, compile and install Cistron Radius.
+
--- /dev/null
+#
+# 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@
+
--- /dev/null
+#
+# 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
--- /dev/null
+
+ 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
+
--- /dev/null
+/*
+
+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
--- /dev/null
+#! /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
+
--- /dev/null
+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])
--- /dev/null
+/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
--- /dev/null
+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.
--- /dev/null
+#! /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
--- /dev/null
+#! /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
--- /dev/null
+#! /bin/sh
+
+case "$1" in
+ remove)
+ /etc/init.d/radiusd stop
+ ;;
+ upgrade)
+ /etc/init.d/radiusd stop
+ ;;
+ failed-upgrade)
+ ;;
+ deconfigure)
+ ;;
+esac
+
+exit 0
--- /dev/null
+#! /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
--- /dev/null
+
+
+ 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).
+
--- /dev/null
+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
+
--- /dev/null
+
+@INCLUDE@ @IQUOTE@../Make.inc@IQUOTE@
+
+all:
+
+install:
+
+clean:
+
--- /dev/null
+
+ 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
+
--- /dev/null
+
+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
--- /dev/null
+
+ 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
+
--- /dev/null
+
+ 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.
+
--- /dev/null
+.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.
--- /dev/null
+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);
+
+}
--- /dev/null
+
+ 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
+
+
--- /dev/null
+.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)
--- /dev/null
+.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)
--- /dev/null
+
+
+ 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.
+
--- /dev/null
+
+ 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.
+
--- /dev/null
+.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.
--- /dev/null
+.so man7/undocumented.7
--- /dev/null
+.so man7/undocumented.7
--- /dev/null
+.so man7/undocumented.7
--- /dev/null
+.so man7/undocumented.7
--- /dev/null
+.so man7/undocumented.7
--- /dev/null
+.so man7/undocumented.7
--- /dev/null
+
+@INCLUDE@ @IQUOTE@../Make.inc@IQUOTE@
+
+all:
+
+install:
+
+clean:
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#\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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+# -*- 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
+}
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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.
--- /dev/null
+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
--- /dev/null
+# 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
+}
--- /dev/null
+#%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
--- /dev/null
+#!/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
--- /dev/null
+
+@INCLUDE@ @IQUOTE@../Make.inc@IQUOTE@
+
+all:
+
+install:
+
+clean:
+
--- /dev/null
+#! /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
+
--- /dev/null
+#! /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
+
--- /dev/null
+#! /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
--- /dev/null
+#!/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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+#\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
--- /dev/null
+#
+# 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
+
--- /dev/null
+/* 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
--- /dev/null
+/* 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
+
--- /dev/null
+/*
+ * 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 *);
+
--- /dev/null
+/* 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 *));
+
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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);
+
--- /dev/null
+
+@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:
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/* 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;
+}
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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");
+ }
+}
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+#
+# 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)
+
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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"
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
--- /dev/null
+
+@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)
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+#! @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);
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+#! /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 "};"
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+#!/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.$$
+
--- /dev/null
+/*
+ * 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;
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+#! /bin/sh
+
+prefix = @prefix@
+localstatedir = @localstatedir@
+logdir = @logdir@
+
+exec last -f $logdir/radwtmp "$@"
--- /dev/null
+#! /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
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+#
+# 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
+
--- /dev/null
+
+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).
+
--- /dev/null
+#!/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
--- /dev/null
+TARGET = rlm_example
+
+SRCS = rlm_example.c
+
+include ../rules.mak
+
--- /dev/null
+#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 */
+};
--- /dev/null
+TARGET = rlm_files
+SRCS = rlm_files.c
+
+include ../rules.mak
--- /dev/null
+/*
+ * 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 */
+};
+
--- /dev/null
+TARGET = rlm_pam
+SRCS = rlm_pam.c
+LIBS = -lpam -ldl
+
+include ../rules.mak
+
+config.mak:
+ @../checkconfig -l LIBPAM pam_start -lpam -ldl
--- /dev/null
+/*
+ * 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 */
+};
+
--- /dev/null
+TARGET = rlm_preprocess
+SRCS = rlm_preprocess.c
+
+include ../rules.mak
--- /dev/null
+/*
+ * 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 */
+};
+
--- /dev/null
+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
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+#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
--- /dev/null
+HAVE_CRYPT_H=
+LIBCRYPT=-lcrypt
+HAVE_GETSPNAM=
+ETC_SHADOW=/etc/shadow
+HAVE_SHADOW_H=
+HAVE_GETUSERSHELL=
--- /dev/null
+/*
+ * 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 */
+};
+
--- /dev/null
+#######################################################################
+#
+# 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
--- /dev/null
+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
+
--- /dev/null
+
+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
+
--- /dev/null
+
+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
+}
+
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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;
+
--- /dev/null
+#
+# 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
+