char *usersfile;
char *acctusersfile;
time_t next_reload;
+ time_t lastusersload;
+ time_t lastacctusersload;
};
/* Function declarations */
PAIR_LIST **newhash=NULL, **oldhash=NULL;
PAIR_LIST *newdefaults=NULL, *newacctusers, *cur=NULL;
PAIR_LIST *olddefaults=NULL, *oldacctusers=NULL;
+ struct stat statbuf;
+ int reloadusers = 1;
+ int reloadacctusers = 1;
/*
* Allocate space for hash table here
memset((PAIR_LIST *)newhash, 0, memsize);
+ /* Check acct_users last modification time */
+ if ((stat(inst->acctusersfile, &statbuf) != -1)
+ && (statbuf.st_mtime <= inst->lastacctusersload)) {
+ DEBUG2("rlm_fastusers: File %s was unchanged. Not reloading.",
+ inst->acctusersfile);
+ reloadacctusers = 0;
+ rcode = 0;
+ }
+ else
/* Read acct_users */
rcode = fastuser_getfile(inst, inst->acctusersfile, NULL, &newacctusers, 1);
+
if (rcode != 0) {
radlog(L_ERR|L_CONS, "rlm_fastusers: Errors reading %s", inst->usersfile);
return -1;
}
+ /* Check users last modification time */
+ if ((stat(inst->usersfile, &statbuf) != -1)
+ && (statbuf.st_mtime <= inst->lastusersload)) {
+ DEBUG2("rlm_fastusers: File %s was unchanged. Not reloading.",
+ inst->usersfile);
+ reloadusers = 0;
+ rcode = 0;
+ /* This was allocated earlier but will remain unused */
+ free(newhash);
+ }
+ else
/* Read users */
rcode = fastuser_getfile(inst, inst->usersfile, &newdefaults, newhash, 0);
+
if (rcode != 0) {
radlog(L_ERR|L_CONS, "rlm_fastusers: Errors reading %s", inst->usersfile);
return -1;
}
- /*
- * We need to do this now so that users auths
- * aren't blocked while we free the old table
- * below
- */
- oldacctusers = inst->acctusers;
- inst->acctusers = newacctusers;
- oldhash = inst->hashtable;
- inst->hashtable = newhash;
- olddefaults = inst->defaults;
- inst->defaults = newdefaults;
+ if (reloadusers) {
+ /*
+ * We need to do this now so that users auths
+ * aren't blocked while we free the old table
+ * below
+ */
+ inst->lastusersload = time(NULL);
+ oldhash = inst->hashtable;
+ inst->hashtable = newhash;
+ olddefaults = inst->defaults;
+ inst->defaults = newdefaults;
- /*
- * When we get here, we assume the hash built properly.
- * So we begin to tear down the old one
- */
- if(oldhash) {
- for(hashindex=0; hashindex<inst->hashsize; hashindex++) {
- if(oldhash[hashindex]) {
- cur = oldhash[hashindex];
- pairlist_free(&cur);
- }
- }
- free(oldhash);
+ /*
+ * When we get here, we assume the hash built properly.
+ * So we begin to tear down the old one
+ */
+ if (oldhash) {
+ for(hashindex=0; hashindex<inst->hashsize; hashindex++) {
+ if(oldhash[hashindex]) {
+ cur = oldhash[hashindex];
+ pairlist_free(&cur);
+ }
+ }
+ free(oldhash);
+ }
pairlist_free(&olddefaults);
+ }
+ if (reloadacctusers) {
+ inst->lastacctusersload = time(NULL);
+ oldacctusers = inst->acctusers;
+ inst->acctusers = newacctusers;
pairlist_free(&oldacctusers);
}
inst->next_reload = time(NULL) + inst->hash_reload;
inst->hashtable = NULL;
+ inst->lastusersload = 0;
+ inst->lastacctusersload = 0;
if(fastuser_buildhash(inst) < 0) {
radlog(L_ERR, "rlm_fastusers: error building user hash. aborting");
return -1;
#include <string.h>
#include <grp.h>
#include <pwd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include "config.h"
const char *radwtmp;
int usegroup;
struct pwcache *cache;
+ time_t cache_reload;
+ time_t next_reload;
+ time_t last_reload;
};
static CONF_PARSER module_config[] = {
offsetof(struct unix_instance,radwtmp), NULL, "${logdir}/radwtmp" },
{ "usegroup", PW_TYPE_BOOLEAN,
offsetof(struct unix_instance,usegroup), NULL, "no" },
+ { "cache_reload", PW_TYPE_INTEGER,
+ offsetof(struct unix_instance,cache_reload), NULL, "600" },
{ NULL, -1, 0, NULL, NULL } /* end the list */
};
free(inst);
return -1;
}
+
+ if (inst->cache_reload) {
+ inst->last_reload = 0;
+ inst->next_reload = time(NULL) + inst->cache_reload;
+ }
} else {
inst->cache = NULL;
}
char *shell;
#endif
+ /* See if we should refresh the cache */
+ if (inst->cache && inst->cache_reload
+ && (inst->next_reload < request->timestamp)) {
+ /* Time to refresh, maybe ? */
+ int must_reload = 0;
+ struct stat statbuf;
+
+ DEBUG2("rlm_users : Time to refresh cache.");
+ /* Check if any of the files has changed */
+ if (inst->passwd_file
+ && (stat(inst->passwd_file, &statbuf) != -1)
+ && (statbuf.st_mtime > inst->last_reload)) {
+ must_reload++;
+ }
+
+ if (inst->shadow_file
+ && (stat(inst->shadow_file, &statbuf) != -1)
+ && (statbuf.st_mtime > inst->last_reload)) {
+ must_reload++;
+ }
+
+ if (inst->group_file
+ && (stat(inst->group_file, &statbuf) != -1)
+ && (statbuf.st_mtime > inst->last_reload)) {
+ must_reload++;
+ }
+
+ if (must_reload) {
+ /* Build a new cache to replace old one */
+ struct pwcache *oldcache;
+ struct pwcache *newcache = unix_buildpwcache(
+ inst->passwd_file,
+ inst->shadow_file,
+ inst->group_file);
+
+ if (newcache) {
+ oldcache = inst->cache;
+ inst->cache = newcache;
+ unix_freepwcache(oldcache);
+
+ inst->last_reload = time(NULL);
+ }
+ } else {
+ DEBUG2("rlm_users : Files were unchanged. Not reloading.");
+ }
+
+ /* Schedule next refresh */
+ inst->next_reload = time(NULL) + inst->cache_reload;
+ }
+
/*
* We can only authenticate user requests which HAVE
* a User-Name attribute.