diff options
Diffstat (limited to 'src/modules/rlm_expiration/rlm_expiration.c')
-rw-r--r-- | src/modules/rlm_expiration/rlm_expiration.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/modules/rlm_expiration/rlm_expiration.c b/src/modules/rlm_expiration/rlm_expiration.c new file mode 100644 index 0000000..0768405 --- /dev/null +++ b/src/modules/rlm_expiration/rlm_expiration.c @@ -0,0 +1,131 @@ +/* + * This program is 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * $Id$ + * @file rlm_expiration.c + * @brief Lockout user accounts based on control attributes. + * + * @copyright 2001,2006 The FreeRADIUS server project + * @copyright 2004 Kostas Kalevras <kkalev@noc.ntua.gr> + */ +RCSID("$Id$") + +#include <freeradius-devel/radiusd.h> +#include <freeradius-devel/modules.h> + +#include <ctype.h> + +/* + * Check if account has expired, and if user may login now. + */ +static rlm_rcode_t CC_HINT(nonnull) mod_authorize(UNUSED void *instance, REQUEST *request) +{ + VALUE_PAIR *vp, *check_item; + char date[50]; + + check_item = fr_pair_find_by_num(request->config, PW_EXPIRATION, 0, TAG_ANY); + if (!check_item) return RLM_MODULE_NOOP; + + /* + * Has this user's password expired? + * + * If so, remove ALL reply attributes, + * and add our own Reply-Message, saying + * why they're being rejected. + */ + if (((time_t) check_item->vp_date) <= request->timestamp) { + vp_prints_value(date, sizeof(date), check_item, 0); + REDEBUG("Account expired at '%s'", date); + + return RLM_MODULE_USERLOCK; + } else { + if (RDEBUG_ENABLED) { + vp_prints_value(date, sizeof(date), check_item, 0); + RDEBUG("Account will expire at '%s'", date); + } + } + + /* + * Else the account hasn't expired, but it may do so + * in the future. Set Session-Timeout. + */ + vp = fr_pair_find_by_num(request->reply->vps, PW_SESSION_TIMEOUT, 0, TAG_ANY); + if (!vp) { + vp = radius_pair_create(request->reply, &request->reply->vps, PW_SESSION_TIMEOUT, 0); + vp->vp_date = (uint32_t) (((time_t) check_item->vp_date) - request->timestamp); + } else if (vp->vp_date > ((uint32_t) (((time_t) check_item->vp_date) - request->timestamp))) { + vp->vp_date = (uint32_t) (((time_t) check_item->vp_date) - request->timestamp); + } + + return RLM_MODULE_OK; +} + +/* + * Compare the expiration date. + */ +static int expirecmp(UNUSED void *instance, REQUEST *req, UNUSED VALUE_PAIR *request, VALUE_PAIR *check, + UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs) +{ + time_t now = 0; + + now = (req) ? req->timestamp : time(NULL); + + if (now <= ((time_t) check->vp_date)) + return 0; + return +1; +} + + +/* + * Do any per-module initialization that is separate to each + * configured instance of the module. e.g. set up connections + * to external databases, read configuration files, set up + * dictionary entries, etc. + * + * If configuration information is given in the config section + * that must be referenced in later calls, store a handle to it + * in *instance otherwise put a null pointer there. + */ +static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance) +{ + /* + * Register the expiration comparison operation. + */ + paircompare_register(dict_attrbyvalue(PW_EXPIRATION, 0), NULL, false, expirecmp, instance); + return 0; +} + +/* + * The module name should be the only globally exported symbol. + * That is, everything else should be 'static'. + * + * If the module needs to temporarily modify it's instantiation + * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE. + * The server will then take care of ensuring that the module + * is single-threaded. + */ +extern module_t rlm_expiration; +module_t rlm_expiration = { + .magic = RLM_MODULE_INIT, + .name = "expiration", + .type = RLM_TYPE_THREAD_SAFE, + .instantiate = mod_instantiate, + .methods = { + [MOD_AUTHORIZE] = mod_authorize, + [MOD_POST_AUTH] = mod_authorize + }, +}; |