Auto-reload for rlm_fastusers and rlm_unix
authoraland <aland>
Mon, 22 Oct 2001 15:13:11 +0000 (15:13 +0000)
committeraland <aland>
Mon, 22 Oct 2001 15:13:11 +0000 (15:13 +0000)
Patch from Philippe Levan <levan@epix.net>

raddb/radiusd.conf.in
src/modules/rlm_fastusers/rlm_fastusers.c
src/modules/rlm_unix/rlm_unix.c

index 78f9c3f..33b0744 100644 (file)
@@ -334,6 +334,8 @@ modules {
                #
                # allowed values: {no, yes}
                cache = no
+               # Reload the cache every 600 seconds (10mins). 0 to disable.
+               cache_reload = 600
 
                #
                #  Define the locations of the normal passwd, shadow, and
index d7fcd34..c97bed8 100644 (file)
@@ -55,6 +55,8 @@ struct fastuser_instance {
        char *usersfile;
        char *acctusersfile;
        time_t next_reload;
+       time_t lastusersload;
+       time_t lastacctusersload;
 };
 
 /* Function declarations */
@@ -102,6 +104,9 @@ static int fastuser_buildhash(struct fastuser_instance *inst) {
        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
@@ -112,45 +117,73 @@ static int fastuser_buildhash(struct fastuser_instance *inst) {
 
        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);
        }
 
@@ -500,6 +533,8 @@ static int fastuser_instantiate(CONF_SECTION *conf, void **instance)
 
        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;
index 8646ef0..3159c5e 100644 (file)
@@ -32,6 +32,8 @@ static const char rcsid[] = "$Id$";
 #include       <string.h>
 #include       <grp.h>
 #include       <pwd.h>
+#include       <sys/types.h>
+#include       <sys/stat.h>
 
 #include "config.h"
 
@@ -71,6 +73,9 @@ struct unix_instance {
        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[] = {
@@ -89,6 +94,8 @@ 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 */
 };
@@ -230,6 +237,11 @@ static int unix_instantiate(CONF_SECTION *conf, void **instance)
                        free(inst);
                        return -1;
                }
+
+               if (inst->cache_reload) {
+                       inst->last_reload = 0;
+                       inst->next_reload = time(NULL) + inst->cache_reload;
+               }
        } else {
                inst->cache = NULL;
        }
@@ -312,6 +324,56 @@ static int unix_authenticate(void *instance, REQUEST *request)
        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.