diff -urN radiusd-cistron-1.6-dist/doc/README.db-file radiusd-cistron-1.6/doc/README.db-file
--- radiusd-cistron-1.6-dist/doc/README.db-file	1969-12-31 18:00:00.000000000 -0600
+++ radiusd-cistron-1.6/doc/README.db-file	2003-06-02 11:43:07.000000000 -0500
@@ -0,0 +1,50 @@
+Berkeley DB file authentication support for Cistron RADIUSD
+
+0. Introduction
+
+   Berkeley DB file authentication was written by Chris Adams
+   <cmadams@hiwaay.net>.
+
+1. Usage
+
+   Use DB-File = "passwd.db", Auth-Type = DB-File in the users file as
+   check items.  This will cause the specified Berkeley DB file (in HASH
+   format) to be opened and the username used as a key to find an entry.
+   Entries are in the same form as the Apache auth_db file; the username
+   is the key and the value is in the form:
+
+	cryptedpass:group[,group...]
+
+   You can also use a check item list like DB-File = "passwd.db",
+   Group = "Mailbox", Auth-Type = Reject to lookup an entry, check for a
+   specific group, and reject the auth request based on the group.
+
+2. Notes
+
+   This uses flock() to get a read lock on the file with a 3 second
+   timeout.  Any updates to the database should also use flock() to keep
+   radiusd from seeing an update in process (which could cause the
+   radiusd process to crash or see incorrect data).
+
+   This uses the old-style (version 1) DB access methods.  If db.h is
+   from a newer version and you have a db_185.h, add -DDB185 to the
+   DBFILE definition.
+
+3. TODO
+
+   Other locking methods should be supported for platforms where flock()
+   doesn't work right (or if the .db file lives on NFS).
+
+   Update to use a newer interface to the DB library (maybe one that
+   includes locking in the library so radiusd doesn't have to worry
+   about it at all).
+
+4. Example
+
+DEFAULT	DB-File = "passwd.db", Group = "Mailbox", Auth-Type = Reject
+	Reply-Message = "Mailbox accounts don't get dialup access"
+
+DEFAULT	DB-File = "passwd.db", Auth-Type = DB-File
+	Session-Timeout = 86400,
+	Framed-Protocol = PPP
+
diff -urN radiusd-cistron-1.6-dist/raddb/dictionary.standard radiusd-cistron-1.6/raddb/dictionary.standard
--- radiusd-cistron-1.6-dist/raddb/dictionary.standard	2003-04-10 09:17:10.000000000 -0500
+++ radiusd-cistron-1.6/raddb/dictionary.standard	2003-06-02 11:27:06.000000000 -0500
@@ -113,6 +113,7 @@
 ATTRIBUTE	Pam-Auth		1041	string
 ATTRIBUTE	Login-Time		1042	string
 ATTRIBUTE	Realm			1045	string
+ATTRIBUTE	DB-File			1046	string
 ATTRIBUTE	Client-IP-Address	1052	ipaddr
 
 #
@@ -231,6 +232,7 @@
 #
 #	Cistron extensions
 #
+VALUE		Auth-Type		DB-File			252
 VALUE		Auth-Type		Pam			253
 VALUE		Auth-Type		Accept			254
 
diff -urN radiusd-cistron-1.6-dist/src/Make.inc radiusd-cistron-1.6/src/Make.inc
--- radiusd-cistron-1.6-dist/src/Make.inc	2003-06-02 11:23:22.000000000 -0500
+++ radiusd-cistron-1.6/src/Make.inc	2003-06-02 11:26:03.000000000 -0500
@@ -15,7 +15,7 @@
 
 SERVER_OBJS   = radiusd.o files.o acct.o pam.o version.o proxy.o \
 			exec.o auth.o timestr.o cache.o readusers.o \
-			crypt16.o
+			crypt16.o dbfile.o
 LIB_OBJS      = dict.o util.o md5.o attrprint.o radius.o log.o pair.o \
 			encrattr.o filters.o
 
@@ -32,7 +32,7 @@
 radiusd: $(SERVER_OBJS) $(LIB_OBJS)
 	$(CC) $(LDFLAGS) -o radiusd $(SERVER_OBJS) \
 	$(LIB_OBJS) \
-	$(LIBS) $(LCRYPT) $(PAMLIB) $(DBMLIB)
+	$(LIBS) $(LCRYPT) $(PAMLIB) $(DBMLIB) $(DBLIB)
 
 radiusd.o: radiusd.c $(INCLUDES)
 	$(CC) $(CFLAGS) $(DIRS) $(DBM) -c radiusd.c
@@ -50,7 +50,7 @@
 	$(CC) $(CFLAGS) $(DIRS) -c dict.c
 
 files.o: files.c $(INCLUDES)
-	$(CC) $(CFLAGS) $(DIRS) $(DBM) $(PAM) -c files.c
+	$(CC) $(CFLAGS) $(DIRS) $(DBM) $(PAM) $(DBFILE) -c files.c
 
 radius.o: radius.c $(INCLUDES)
 	$(CC) $(CFLAGS) $(DIRS) -c radius.c
@@ -77,7 +77,7 @@
 	$(CC) $(CFLAGS) $(DIRS) -c exec.c
 
 auth.o:  auth.c $(INCLUDES)
-	$(CC) $(CFLAGS) $(DIRS) $(PAM) -c auth.c
+	$(CC) $(CFLAGS) $(DIRS) $(PAM) $(DBFILE) -c auth.c
 
 pair.o: pair.c $(INCLUDES)
 	$(CC) $(CFLAGS) $(DIRS) $(PAM) -c pair.c
@@ -85,6 +85,9 @@
 version.o: version.c $(INCLUDES)
 	$(CC) $(CFLAGS) $(DIRS) $(DBM) $(PAM) -o version.o -c version.c
 
+dbfile.o: dbfile.c $(INCLUDES)
+	$(CC) $(CFLAGS) $(DIRS) $(DBFILE) -c dbfile.c
+
 crypt16.o: crypt16.c $(INCLUDES)
 	$(CC) $(CFLAGS) $(DIRS) -c crypt16.c
 
diff -urN radiusd-cistron-1.6-dist/src/Makefile radiusd-cistron-1.6/src/Makefile
--- radiusd-cistron-1.6-dist/src/Makefile	2003-05-23 10:54:09.000000000 -0500
+++ radiusd-cistron-1.6/src/Makefile	2003-06-02 11:23:33.000000000 -0500
@@ -31,6 +31,9 @@
 INSTALL = install
 DINSTALL = install -d
 
+DBFILE	= -DDBFILE -DDB185
+DBLIB	= -ldb
+
 BINDIR  = /usr/local/bin
 SBINDIR = /usr/local/sbin
 MANDIR  = /usr/local/man
diff -urN radiusd-cistron-1.6-dist/src/Makefile.lnx radiusd-cistron-1.6/src/Makefile.lnx
--- radiusd-cistron-1.6-dist/src/Makefile.lnx	2003-05-23 10:54:09.000000000 -0500
+++ radiusd-cistron-1.6/src/Makefile.lnx	2003-06-02 11:23:33.000000000 -0500
@@ -31,6 +31,9 @@
 INSTALL = install
 DINSTALL = install -d
 
+DBFILE	= -DDBFILE -DDB185
+DBLIB	= -ldb
+
 BINDIR  = /usr/local/bin
 SBINDIR = /usr/local/sbin
 MANDIR  = /usr/local/man
diff -urN radiusd-cistron-1.6-dist/src/auth.c radiusd-cistron-1.6/src/auth.c
--- radiusd-cistron-1.6-dist/src/auth.c	2003-04-03 11:23:17.000000000 -0600
+++ radiusd-cistron-1.6/src/auth.c	2003-06-02 11:23:33.000000000 -0500
@@ -278,6 +278,10 @@
         VALUE_PAIR      *pampair;
 	char		*pamauth = NULL;
 #endif
+#ifdef DBFILE
+	VALUE_PAIR	*dbpair;
+	char		*dbfile = NULL;
+#endif
 	char		string[AUTH_STRING_LEN];
 	char		name[AUTH_STRING_LEN];
 	char		*ptr;
@@ -318,6 +322,12 @@
 	if (auth_item == NULL)
 		return result;
 
+#ifdef DBFILE
+        if ((dbpair = pairfind(check_item, PW_DBFILE)) != NULL) {
+		dbfile = dbpair->strvalue;
+        }
+#endif
+
 	/*
 	 *	Decrypt the password.
 	 */
@@ -394,6 +404,16 @@
 			result = -1;
 #endif
 			break;
+		case PW_AUTHTYPE_DB:
+#ifdef DBFILE
+			DEBUG2("  auth: DB");
+			if (db_pass(name, string, dbfile) != 0)
+				result = -1;
+#else
+			log(L_ERR, "%s: DB file auth not available", name);
+			result = -1;
+#endif
+			break;
 		case PW_AUTHTYPE_CRYPT:
 			DEBUG2("  auth: Crypt");
 			if (password_pair == NULL) {
diff -urN radiusd-cistron-1.6-dist/src/dbfile.c radiusd-cistron-1.6/src/dbfile.c
--- radiusd-cistron-1.6-dist/src/dbfile.c	1969-12-31 18:00:00.000000000 -0600
+++ radiusd-cistron-1.6/src/dbfile.c	2003-06-02 11:23:33.000000000 -0500
@@ -0,0 +1,266 @@
+#ifdef DBFILE
+
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 1
+#endif
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE 1
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <limits.h>
+#include <time.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+#ifdef DB185
+#include <db_185.h>
+#else
+#include <db.h>
+#endif
+
+#include "radiusd.h"
+
+#define TIMEOUT 3
+
+/* User record structure */
+typedef struct {
+	char file[256];
+	char *user;
+	char *pass;
+	char **groups;
+} DBUSER;
+
+/* Single user "cache" */
+static DBUSER dbcache;
+
+/* Used for alarm */
+sigjmp_buf env;
+
+void
+myalarm (num)
+	int num;
+{
+	siglongjmp (env, 1);
+}
+
+
+/*
+ * Lookup an entry in a DB file
+ */
+DBUSER *
+lookup_entry (dbfile, user)
+	char *dbfile;
+	char *user;
+{
+	DB *db;
+	DBT key, data;
+	int lock;
+	int result;
+	char *p, *q;
+	char *str;
+	int size;
+	int oldalarm;
+	struct sigaction newsig, oldsig;
+	int i;
+	char buf[256];
+
+	/* declare these static to avoid warnings about setlongjmp */
+	static int timeout;
+	static char *dbf;
+
+	/* Build the full path */
+	dbf = dbfile;
+	if (dbf[0] != '/') {
+		sprintf (buf, "%.200s/%.50s", radius_dir, dbf);
+		dbf = buf;
+	}
+
+	/* Check the "cache" */
+	if (dbcache.file[0] && (strcmp (dbcache.file, dbf) == 0)
+	    && (strcmp (dbcache.user, user) == 0))
+		return (&dbcache);
+
+	/* Clear the "cache" */
+	if (dbcache.file[0]) {
+		free (dbcache.user);
+		free (dbcache.pass);
+		free (dbcache.groups);
+		dbcache.file[0] = '\0';
+	}
+
+	/* Lock the database */
+	timeout = 0;
+	newsig.sa_handler = myalarm;
+	newsig.sa_flags = 0;
+
+	if ((lock = open (dbf, O_RDONLY)) == -1) {
+		log (L_ERR, "dbfile open %s failed: %m", dbf);
+		return (NULL);
+	}
+	if (sigaction (SIGALRM, &newsig, &oldsig)) {
+		log (L_ERR, "dbfile set signal: %m");
+		close (lock);
+		return (NULL);
+	}
+	if (sigsetjmp (env, 1) != 0)
+		timeout = 1;
+
+	oldalarm = alarm (0);
+	if (timeout == 0) {
+		alarm (TIMEOUT);
+		result = flock (lock, LOCK_SH);
+	} else
+		result = -1;
+
+	sigaction (SIGALRM, &oldsig, NULL);
+	alarm (oldalarm);
+	if (result != 0) {
+		if (timeout)
+			log (L_ERR, "dbfile flock timeout");
+		else
+			log (L_ERR, "dbfile flock SH failed: %m");
+		close (lock);
+		return (NULL);
+	}
+
+	/* Open the database */
+	db = dbopen (dbf, O_RDONLY, 0, DB_HASH, NULL);
+	if (db == NULL) {
+		log (L_ERR, "dbfile dbopen %s failed: %m", dbf);
+		flock (lock, LOCK_UN);
+		close (lock);
+		return (NULL);
+	}
+
+	/* Look up the user */
+	str = NULL;
+	key.size = strlen (user);
+	key.data = user;
+	result = db->get (db, &key, &data, 0);
+	if (result == -1)
+		/* Oops, something bad happened */
+		log (L_ERR, "db get failed: %m");
+	else if (result == 0) {
+		/* Got a key match, save the value */
+		p = data.data;
+		size = data.size;
+		if (p[size - 1])
+			/* Not null terminated */
+			size ++;
+		if ((str = malloc (sizeof (char) * size)) == NULL) {
+			log (L_ERR, "malloc str failed: %m");
+			str = NULL;
+		} else {
+			strncpy (str, p, data.size);
+			str[data.size] = '\0';
+		}
+	}
+
+	/* Close and unlock the database */
+	db->close (db);
+	flock (lock, LOCK_UN);
+	close (lock);
+
+	/* If there is not a result to parse, return */
+	if (! str)
+		return (NULL);
+
+	/* Save the password */
+	p = strchr (str, ':');
+	dbcache.pass = str;
+
+	if (p) {
+		/* Count the groups */
+		*p++ = '\0';
+		for (i = 1, q = p; q != NULL; i++)
+			if ((q = strchr (q, ',')) != NULL)
+				q++;
+	} else {
+		/* No groups */
+		i = 1;
+	}
+	/* Save the groups */
+	if ((dbcache.groups = malloc (sizeof (char *) * i)) == NULL) {
+		log (L_ERR, "malloc groups failed: %m");
+		free (dbcache.pass);
+		return (NULL);
+	}
+	for (i = 0, q = p; q != NULL; i++) {
+		dbcache.groups[i] = q;
+		if ((q = strchr (q, ',')) != NULL)
+			q++;
+	}
+	dbcache.groups[i] = NULL;
+
+	/* Save the username */
+	if ((dbcache.user = strdup (user)) == NULL) {
+		log (L_ERR, "dup user failed: %m");
+		free (dbcache.pass);
+		free (dbcache.groups);
+		return (NULL);
+	}
+
+	/* Save the filename */
+	strncpy (dbcache.file, dbf, 255);
+
+	return (&dbcache);
+}
+
+
+/*
+ * Check a user's password
+ */
+int
+db_pass (user, pass, dbfile)
+	char *user;
+	char *pass;
+	char *dbfile;
+{
+	DBUSER *ent;
+
+	if ((ent = lookup_entry (dbfile, user)) == NULL)
+		return (-1);
+
+	if (ent->pass[0] == '!') {
+		log (L_AUTH, "User blocked: [%s]", user);
+		return (-1);
+	}
+
+	if (strcmp (crypt (pass, ent->pass), ent->pass) != 0)
+		return (-1);
+
+	return (0);
+}
+
+
+/*
+ * See if a user is a member of a group
+ */
+int
+db_group (user, group, dbfile)
+	char *user;
+	char *group;
+	char *dbfile;
+{
+	DBUSER *ent;
+	int i;
+
+	if ((ent = lookup_entry (dbfile, user)) == NULL)
+		return (-1);
+
+	for (i = 0; ent->groups[i]; i++)
+		if (strcmp (ent->groups[i], group) == 0)
+			return (0);
+
+	return (-1);
+}
+
+#endif
diff -urN radiusd-cistron-1.6-dist/src/files.c radiusd-cistron-1.6/src/files.c
--- radiusd-cistron-1.6-dist/src/files.c	2003-06-02 11:23:22.000000000 -0500
+++ radiusd-cistron-1.6/src/files.c	2003-06-02 11:23:33.000000000 -0500
@@ -294,6 +294,10 @@
 	int result = 0;
 	char username[AUTH_STRING_LEN];
 	int compare;
+#ifdef DBFILE
+	int do_dbfile = 0;
+	char *dbfile = NULL;
+#endif
 
 	username[0] = '\0';
 	while (result == 0 && check_item != NULL) {
@@ -302,11 +306,21 @@
 			 *	Attributes we skip during comparison.
 			 *	These are "server" check items.
 			 */
+#ifdef DBFILE
+			case PW_DBFILE:
+				dbfile = check_item->strvalue;
+				check_item = check_item->next;
+				continue;
+			case PW_AUTHTYPE:
+				if (check_item->lvalue == PW_AUTHTYPE_DB)
+					do_dbfile = 1;
+#else
+			case PW_AUTHTYPE:
+#endif
 			case PW_EXPIRATION:
 			case PW_LOGIN_TIME:
 			case PW_PASSWORD:
 			case PW_CRYPT_PASSWORD:
-			case PW_AUTHTYPE:
 #ifdef PAM /* cjd 19980706 */
                         case PAM_AUTH_ATTR:
 #endif
@@ -380,7 +394,15 @@
 				else
 				if (check_item->attribute == PW_GROUP_NAME ||
 				    check_item->attribute == PW_GROUP) {
-					compare = groupcmp(check_item, username);
+#ifdef DBFILE
+					if (dbfile)
+						compare = db_group(username,
+						    check_item->strvalue,
+						    dbfile);
+					else
+#endif
+						compare = groupcmp(check_item,
+						    username);
 				}
 				else
 				if (check_item->attribute == PW_HUNTGROUP_NAME){
@@ -464,6 +486,10 @@
 	VALUE_PAIR *check_item = check;
 	VALUE_PAIR *auth_item;
 	int result = -1;
+#ifdef DBFILE
+	int do_dbfile = 0;
+	char *dbfile = NULL;
+#endif
 
 	if (check == NULL) return 0;
 
@@ -473,9 +499,19 @@
 			 *	Attributes we skip during comparison.
 			 *	These are "server" check items.
 			 */
+#ifdef DBFILE
+			case PW_DBFILE:
+				dbfile = check_item->strvalue;
+				check_item = check_item->next;
+				continue;
+			case PW_AUTHTYPE:
+				if (check_item->lvalue == PW_AUTHTYPE_DB)
+					do_dbfile = 1;
+#else
+			case PW_AUTHTYPE:
+#endif
 			case PW_EXPIRATION:
 			case PW_PASSWORD:
-			case PW_AUTHTYPE:
 /* cjd 19980706
  */
 #ifdef PAM
@@ -511,6 +547,14 @@
 			case PW_TYPE_STRING:
 				if (check_item->attribute == PW_GROUP_NAME ||
 				    check_item->attribute == PW_GROUP) {
+#ifdef DBFILE
+					if (dbfile &&
+					    db_group(auth_item->strvalue,
+					    check_item->strvalue,
+					    dbfile))
+						result = 0;
+					else
+#endif
 					if (groupcmp(check_item, auth_item->strvalue)==0)
 							result = 0;
 				}
diff -urN radiusd-cistron-1.6-dist/src/radius.h radiusd-cistron-1.6/src/radius.h
--- radiusd-cistron-1.6-dist/src/radius.h	2003-06-02 11:23:22.000000000 -0500
+++ radiusd-cistron-1.6/src/radius.h	2003-06-02 11:23:33.000000000 -0500
@@ -145,6 +145,7 @@
 #define PAM_AUTH_ATTR			1041
 #define PW_LOGIN_TIME			1042
 #define PW_REALM			1045
+#define PW_DBFILE			1046
 #define PW_CLIENT_IP_ADDRESS		1052
 
 /*
@@ -188,6 +189,7 @@
 #define PW_AUTHTYPE_SECURID		2
 #define PW_AUTHTYPE_CRYPT		3
 #define PW_AUTHTYPE_REJECT		4
+#define PW_AUTHTYPE_DB			252
 #define PW_AUTHTYPE_PAM			253
 #define PW_AUTHTYPE_ACCEPT		254
 
diff -urN radiusd-cistron-1.6-dist/src/radiusd.h radiusd-cistron-1.6/src/radiusd.h
--- radiusd-cistron-1.6-dist/src/radiusd.h	2003-06-02 11:23:22.000000000 -0500
+++ radiusd-cistron-1.6/src/radiusd.h	2003-06-02 11:23:33.000000000 -0500
@@ -360,3 +360,7 @@
 #define crypt crypt16
 char *		crypt16 (char *, char *);
 
+/* dbfile.c */
+int		db_pass (char *user, char *pass, char *dbfile);
+int		db_group (char *user, char *group, char *dbfile);
+
