*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * Copyright 2000 The FreeRADIUS server project
+ * Copyright 2000,2006 The FreeRADIUS server project
* Copyright 2000 Jeff Carneal <jeff@apex.net>
*/
-#include "autoconf.h"
-#include "libradius.h"
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
+
+#include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/modules.h>
-#include <sys/socket.h>
-#include <sys/time.h>
#include <sys/stat.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include <fcntl.h>
#include <limits.h>
-#include "radiusd.h"
-#include "modules.h"
-
struct fastuser_instance {
char *compat_mode;
int hash_reload;
/* hash table */
- long hashsize;
+ int hashsize;
PAIR_LIST **hashtable;
PAIR_LIST *defaults;
PAIR_LIST *acctusers;
/* Function declarations */
static int fallthrough(VALUE_PAIR *vp);
static int fastuser_buildhash(struct fastuser_instance *inst);
-static int fastuser_getfile(struct fastuser_instance *inst, const char *filename,
- PAIR_LIST **default_list, PAIR_LIST **pair_list,
+static int fastuser_getfile(struct fastuser_instance *inst, const char *filename,
+ PAIR_LIST **default_list, PAIR_LIST **pair_list,
int isacctfile);
-static int fastuser_hash(const char *s, long hashtablesize);
+static int fastuser_hash(const char *s, int hashtablesize);
static int fastuser_store(PAIR_LIST **hashtable, PAIR_LIST *entry, int idx);
static PAIR_LIST *fastuser_find(REQUEST *request, PAIR_LIST *user,
const char *username);
-static void fastuser_tablestats(PAIR_LIST **hashtable, long size);
-static int fastuser_passcheck(REQUEST *request, PAIR_LIST *user, const char *name);
+static void fastuser_tablestats(PAIR_LIST **hashtable, int size);
-static CONF_PARSER module_config[] = {
- { "usersfile", PW_TYPE_STRING_PTR,
+static const CONF_PARSER module_config[] = {
+ { "usersfile", PW_TYPE_FILENAME,
offsetof(struct fastuser_instance,usersfile), NULL, "${raddbdir}/users_fast" },
- { "acctusersfile", PW_TYPE_STRING_PTR,
+ { "acctusersfile", PW_TYPE_FILENAME,
offsetof(struct fastuser_instance,acctusersfile), NULL, "${raddbdir}/acct_users" },
{ "hashsize", PW_TYPE_INTEGER,
offsetof(struct fastuser_instance,hashsize), NULL, "100000" },
{
VALUE_PAIR *authtype;
- /*
+ /*
* We check for Auth-Type = Reject here
*/
}
static int fastuser_buildhash(struct fastuser_instance *inst) {
- long memsize=0;
+ int memsize=0;
int rcode, hashindex;
PAIR_LIST **newhash=NULL, **oldhash=NULL;
PAIR_LIST *newdefaults=NULL, *newacctusers, *cur=NULL;
int reloadusers = 1;
int reloadacctusers = 1;
- /*
+ /*
* Allocate space for hash table here
*/
memsize = sizeof(PAIR_LIST *) * inst->hashsize;
cur = oldhash[hashindex];
pairlist_free(&cur);
}
- }
+ }
free(oldhash);
}
pairlist_free(&olddefaults);
pairlist_free(&oldacctusers);
}
- if(inst->stats)
+ if(inst->stats)
fastuser_tablestats(inst->hashtable, inst->hashsize);
- return 0;
+ return 0;
}
-static int fastuser_getfile(struct fastuser_instance *inst, const char *filename,
- PAIR_LIST **default_list, PAIR_LIST **pair_list,
+static int fastuser_getfile(struct fastuser_instance *inst, const char *filename,
+ PAIR_LIST **default_list, PAIR_LIST **pair_list,
int isacctfile) {
int rcode;
PAIR_LIST *users = NULL;
int compat_mode = FALSE;
VALUE_PAIR *vp=NULL;
int hashindex = 0;
- long numdefaults = 0, numusers=0;
+ int numdefaults = 0, numusers=0;
radlog(L_INFO, " fastusers: Reading %s", filename);
rcode = pairlist_read(filename, &users, 1);
if (strcmp(inst->compat_mode, "cistron") == 0) {
compat_mode = TRUE;
}
-
+
entry = users;
while (entry) {
if (compat_mode) {
* Ignore attributes which are set
* properly.
*/
- if (vp->operator != T_OP_EQ)
+ if (vp->operator != T_OP_EQ)
continue;
-
+
/*
* If it's a vendor attribute,
- * or it's a wire protocol,
+ * or it's a wire protocol,
* ensure it has '=='.
*/
if (((vp->attribute & ~0xffff) != 0) ||
vp->operator = T_OP_CMP_EQ;
continue;
}
-
+
/*
* Cistron Compatibility mode.
*
vp->operator = T_OP_CMP_EQ;
}
}
-
+
} /* end of loop over check items */
-
-
+
+
/*
* Look for server configuration items
* in the reply list.
log_debug("[%s]:%d WARNING! Check item \"%s\"\n"
"\tfound in reply item list for user \"%s\".\n"
"\tThis attribute MUST go on the first line"
- " with the other check items",
+ " with the other check items",
filename, entry->lineno, vp->name,
entry->name);
}
if(!isacctfile) {
/* Save the DEFAULT entry specially */
if(strcmp(entry->name, "DEFAULT")==0) {
-
+
/* Save this as the last default we've seen */
lastdefault = entry;
numdefaults++;
-
+
/* put it at the end of the list */
if(defaults) {
for(cur=defaults; cur->next; cur=cur->next);
entry->next = NULL;
} else {
defaults = entry;
- defaults->next = NULL;
+ defaults->next = NULL;
}
-
+
} else {
numusers++;
-
+
/* Hash the username */
hashindex = fastuser_hash(entry->name, inst->hashsize);
-
+
/* Store the last default before this entry */
entry->lastdefault = lastdefault;
-
+
/* Store user in the hash */
fastuser_store(pair_list, entry, hashindex);
}
if(!isacctfile && (default_list)) {
*default_list = defaults;
- radlog(L_INFO, "rlm_fastusers: Loaded %ld users and %ld defaults",
+ radlog(L_INFO, "rlm_fastusers: Loaded %d users and %d defaults",
numusers, numdefaults);
} else {
*pair_list = users;
}
/* Hashes the username sent to it and returns index into hashtable */
-int fastuser_hash(const char *s, long hashtablesize) {
- unsigned long hash = 0;
+int fastuser_hash(const char *s, int hashtablesize) {
+ unsigned int hash = 0;
while (*s != '\0') {
hash = hash * 7907 + (unsigned char)*s++;
cur = hashtable[idx];
/* store new record at end of list */
if(cur) {
- while (cur->next != NULL)
+ while (cur->next != NULL)
cur=cur->next;
cur->next = new;
new->next = NULL;
* Looks up user in hashtable. If user can't be found, returns 0.
* Otherwise returns a pointer to the structure for the user
*/
-static PAIR_LIST *fastuser_find(REQUEST *request, PAIR_LIST *user,
+static PAIR_LIST *fastuser_find(REQUEST *request, PAIR_LIST *user,
const char *username)
{
PAIR_LIST *cur=user;
*/
while((cur) && (!userfound)) {
if((strcmp(cur->name, username)==0) &&
- paircmp(request, request->packet->vps, cur->check, &request->reply->vps) == 0) {
- /*
- * Usercollide means we have to compare check pairs
- * AND the password
- */
- if(mainconfig.do_usercollide) {
- if((userfound = fastuser_passcheck(request, cur, username))==0) {
- cur = cur->next;
- }
-
- } else {
+ paircompare(request, request->packet->vps, cur->check, &request->reply->vps) == 0) {
userfound = 1;
DEBUG2(" fastusers: Matched %s at %d", cur->name, cur->lineno);
- }
} else {
cur = cur->next;
}
/*
* Generate and log statistics about our hash table
*/
-static void fastuser_tablestats(PAIR_LIST **hashtable, long size) {
+static void fastuser_tablestats(PAIR_LIST **hashtable, int size) {
int i, count;
int countarray[256];
int toomany=0;
}
}
- for(i=0; i<256; i++)
+ for(i=0; i<256; i++)
if(countarray[i]) {
radlog(L_INFO, "rlm_fastusers: Hash buckets with %d users: %d",
i, countarray[i]);
}
if(toomany) {
- radlog(L_INFO, "rlm_fastusers: Hash buckets with more than 256: %d",
+ radlog(L_INFO, "rlm_fastusers: Hash buckets with more than 256: %d",
toomany);
}
}
-static int fastuser_passcheck(REQUEST *request, PAIR_LIST *user, const char *name)
-{
- int found=0;
- VALUE_PAIR *check_save;
-
- /*
- * We check for REJECT specially here or a REJECT
- * user will never match
- */
- check_save = pairfind(user->check, PW_AUTHTYPE);
- if((check_save) && check_save->lvalue == PW_AUTHTYPE_REJECT) {
- DEBUG2(" fastusers(uc): User '%s' line %d is Auth-Type Reject, but usercollide match",
- user->name, user->lineno);
- return 1;
- }
-
- /* Save the orginal config items */
- check_save = request->config_items;
- request->config_items = NULL;
-
- DEBUG2(" fastusers(uc): Checking %s at %d", user->name, user->lineno);
-
- /* Copy this users check pairs to the request */
- request->config_items = paircopy(user->check);
-
- /* Check the req to see if we matched */
- if(rad_check_password(request)==0) {
- DEBUG2(" fastusers(uc): Matched %s at %d", user->name, user->lineno);
- found = 1;
- }
-
- /* Restore check items */
- pairfree(&request->config_items);
- request->config_items = check_save;
-
- return found;
-}
-
/*
* (Re-)read the "users" file into memory.
*/
radlog(L_INFO, "rlm_fastusers: Reloading fastusers hash");
if(fastuser_buildhash(inst) < 0) {
radlog(L_ERR, "rlm_fastusers: error building user hash. aborting");
- exit(1);
+ return RLM_MODULE_FAIL;
}
}
* Grab the canonical user name.
*/
namepair = request->username;
- name = namepair ? (char *) namepair->strvalue : "NONE";
+ name = namepair ? (char *) namepair->vp_strvalue : "NONE";
/*
* Find the entry for the user.
hashidx = fastuser_hash(name, inst->hashsize);
user = inst->hashtable[hashidx];
if((user=fastuser_find(request, user, name))!=NULL) {
- userfound = 1;
+ userfound = 1;
}
- /*
+ /*
* If there's no lastdefault and we
* don't fallthrough, just copy the
* pairs for this user and return
check_tmp = paircopy(user->check);
pairmove(&request->config_items, &check_tmp);
- pairfree(&check_tmp);
+ pairfree(&check_tmp);
reply_tmp = paircopy(user->reply);
pairmove(&request->reply->vps, &reply_tmp);
}
}
- /*
- * When we get here, we've either found
+ /*
+ * When we get here, we've either found
* the user or not, but to preserve order
* we start at the top of the default
* list and work our way thru
* and return
*/
DEBUG2("rlm_fastusers: checking defaults");
-
+
curdefault = inst->defaults;
while(curdefault) {
- if(paircmp(request, request->packet->vps, curdefault->check,
+ if(paircompare(request, request->packet->vps, curdefault->check,
&request->reply->vps) == 0) {
- DEBUG2(" fastusers: Matched %s at %d",
+ DEBUG2(" fastusers: Matched %s at %d",
curdefault->name, curdefault->lineno);
defaultfound = 1;
check_tmp = paircopy(curdefault->check);
pairmove(&request->config_items, &check_tmp);
- pairfree(&check_tmp);
+ pairfree(&check_tmp);
reply_tmp = paircopy(curdefault->reply);
pairmove(&request->reply->vps, &reply_tmp);
pairfree(&reply_tmp);
- /*
- * There's no fallthru on this default which
- * is *before* we find the user in the file,
- * so we know it's safe to quit here
+ /*
+ * There's no fallthru on this default which
+ * is *before* we find the user in the file,
+ * so we know it's safe to quit here
*/
if (!fallthrough(curdefault->reply))
break;
check_tmp = paircopy(user->check);
pairmove(&request->config_items, &check_tmp);
- pairfree(&check_tmp);
+ pairfree(&check_tmp);
reply_tmp = paircopy(user->reply);
pairmove(&request->reply->vps, &reply_tmp);
return(rad_check_return(user->check));
}
- /*
+ /*
* Find next occurence of THIS user in
* the users file
*/
user=user->next;
user=fastuser_find(request, user, name);
- }
+ }
curdefault = curdefault->next;
}
struct fastuser_instance *inst = instance;
namepair = request->username;
- name = namepair ? (char *) namepair->strvalue : "NONE";
+ name = namepair ? (char *) namepair->vp_strvalue : "NONE";
request_pairs = request->packet->vps;
config_pairs = &request->config_items;
-
+
/*
* Find the entry for the user.
*/
if (strcmp(name, pl->name) && strcmp(pl->name, "DEFAULT"))
continue;
- if (paircmp(request, request_pairs, pl->check, &reply_pairs) == 0) {
+ if (paircompare(request, request_pairs, pl->check, &reply_pairs) == 0) {
DEBUG2(" acct_users: Matched %s at %d",
pl->name, pl->lineno);
found = 1;
cur = inst->hashtable[hashindex];
pairlist_free(&cur);
}
- }
+ }
- free(inst->compat_mode);
free(inst->hashtable);
pairlist_free(&inst->defaults);
pairlist_free(&inst->acctusers);
- free(inst->usersfile);
- free(inst->acctusersfile);
- free(inst);
return 0;
}
/*
* This function is unused
*/
-static int fastuser_accounting(void *instance, REQUEST *request)
+static int fastuser_accounting(void *instance UNUSED, REQUEST *request UNUSED)
{
+ /*
+ * FIXME: should re rather return RLM_MODULE_NOOP here?
+ */
return RLM_MODULE_FAIL;
}
/* globally exported name */
module_t rlm_fastusers = {
+ RLM_MODULE_INIT,
"fastusers",
0, /* type: reserved */
- NULL, /* initialization */
fastuser_instantiate, /* instantiation */
+ fastuser_detach, /* detach */
{
fastuser_authenticate, /* authentication */
fastuser_authorize, /* authorization */
NULL, /* post-proxy */
NULL /* post-auth */
},
- fastuser_detach, /* detach */
- NULL /* destroy */
};