From c0aaa6475b33c75be318e6c8791d259294009112 Mon Sep 17 00:00:00 2001 From: kkalev Date: Mon, 9 Aug 2004 15:31:05 +0000 Subject: [PATCH] Move the Login-Time,Current-Time,Expiration attribute handling to separate modules, rlm_logintime and rlm_expiration. Move timestr.c to rlm_logintime. Update makefiles and radiusd.conf --- raddb/radiusd.conf.in | 40 ++++ src/main/Makefile.in | 5 +- src/main/auth.c | 100 ---------- src/main/valuepair.c | 51 ----- src/modules/rlm_expiration/Makefile | 4 + src/modules/rlm_expiration/rlm_expiration.c | 225 +++++++++++++++++++++ src/modules/rlm_logintime/Makefile | 4 + src/modules/rlm_logintime/rlm_logintime.c | 275 ++++++++++++++++++++++++++ src/{main => modules/rlm_logintime}/timestr.c | 0 src/modules/stable | 2 + 10 files changed, 551 insertions(+), 155 deletions(-) create mode 100644 src/modules/rlm_expiration/Makefile create mode 100644 src/modules/rlm_expiration/rlm_expiration.c create mode 100644 src/modules/rlm_logintime/Makefile create mode 100644 src/modules/rlm_logintime/rlm_logintime.c rename src/{main => modules/rlm_logintime}/timestr.c (100%) diff --git a/raddb/radiusd.conf.in b/raddb/radiusd.conf.in index 692c22e..5bf6799 100644 --- a/raddb/radiusd.conf.in +++ b/raddb/radiusd.conf.in @@ -1375,6 +1375,46 @@ $INCLUDE ${confdir}/eap.conf } # + # The expiration module. This handles the Expiration attribute + # It should be included in the *end* of the authorize section + # in order to handle user Expiration. It should also be included + # in the instantiate section in order to register the Expiration + # compare function + # + expiration { + # + # The Reply-Message which will be sent back in case the + # account has expired. Dynamic substitution is supported + # + reply-message = "Password Has Expired\r\n" +# reply-message = "Your account has expired, %{User-Name}\r\n" + } + + # + # The logintime module. Handles the Login-Time and Current-Time attributes. + # It should be included in the *end* of the authorize section + # in order to handle Login-Time checks. It should also be included in + # the instantiate section in order to register the Current-Time compare + # function. + # If the user is allowed to logon a Session-Timeout is calculated based on the + # remaining time. + # + logintime { + # + # The Reply-Message which will be sent back in case the account + # is calling outside of the allowed timespan. Dynamic substitution is + # supported. + # + reply-message = "You are calling outside your allowed timespan\r\n" +# reply-message = "Outside allowed timespan (%{check:Login-Time}), %{User-Name}\r\n" + # + # The minimum timeout (in seconds) a user is allowed to have. If the calculated + # timeout is lower we don't allow the logon. Some NASes do not handle + # values lower than 60 seconds well. + # + minimum-timeout = 60 + } + # # Execute external programs # # This module is useful only for 'xlat'. To use it, diff --git a/src/main/Makefile.in b/src/main/Makefile.in index 8d5c937..f9500bc 100644 --- a/src/main/Makefile.in +++ b/src/main/Makefile.in @@ -5,7 +5,7 @@ include ../../Make.inc SERVER_OBJS = radiusd.o files.o util.o acct.o nas.o log.o valuepair.o \ - version.o proxy.o exec.o auth.o timestr.o conffile.o \ + version.o proxy.o exec.o auth.o conffile.o \ modules.o modcall.o session.o xlat.o threads.o smux.o \ radius_snmp.o client.o request_list.o mainconfig.o INCLUDES = ../include/radiusd.h ../include/radius.h ../include/libradius.h ../include/conf.h ../include/autoconf.h @@ -82,9 +82,6 @@ conffile.o: conffile.c $(INCLUDES) ../include/modules.h mainconfig.o: mainconfig.c $(INCLUDES) ../include/modules.h $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c mainconfig.c -timestr.o: timestr.c $(INCLUDES) - $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c timestr.c - modules.o: modules.c $(INCLUDES) $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(VFLAGS) $(INCLTDL) -c modules.c diff --git a/src/main/auth.c b/src/main/auth.c index ec3b3ff..2188406 100644 --- a/src/main/auth.c +++ b/src/main/auth.c @@ -60,45 +60,6 @@ char *auth_name(char *buf, size_t buflen, REQUEST *request, int do_cli) { } -/* - * Check if account has expired, and if user may login now. - */ -static int check_expiration(REQUEST *request) -{ - int result; - VALUE_PAIR *check_item = request->config_items; - - result = 0; - while (result == 0 && check_item != NULL) { - - /* - * Check expiration date if we are doing password aging. - */ - if (check_item->attribute == PW_EXPIRATION) { - /* - * 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 (check_item->lvalue < (unsigned) time(NULL)) { - VALUE_PAIR *vp; - - result = -1; - vp = pairmake("Reply-Message", - "Password Has Expired\r\n", - T_OP_ADD); - pairfree(&request->reply->vps); - request->reply->vps = vp; - break; - } - } - check_item = check_item->next; - } - return result; -} - /* * Make sure user/pass are clean @@ -613,8 +574,6 @@ autz_redo: * Validate the user */ do { - if ((result = check_expiration(request)) < 0) - break; result = rad_check_password(request); if (result > 0) { /* don't reply! */ @@ -716,65 +675,6 @@ autz_redo: } } - if (result >= 0 && - (check_item = pairfind(request->config_items, PW_LOGIN_TIME)) != NULL) { - - /* - * Authentication is OK. Now see if this - * user may login at this time of the day. - */ - r = timestr_match((char *)check_item->strvalue, - request->timestamp); - - if (r == 0) { /* unlimited */ - /* - * Do nothing: login-time is OK. - */ - - /* - * Session-Timeout needs to be at least - * 60 seconds, some terminal servers - * ignore smaller values. - */ - } else if (r < 60) { - /* - * User called outside allowed time interval. - */ - result = -1; - user_msg = "You are calling outside your allowed timespan\r\n"; - - request->reply->code = PW_AUTHENTICATION_REJECT; - pairfree(&request->reply->vps); - - tmp = pairmake("Reply-Message", user_msg, T_OP_SET); - request->reply->vps = tmp; - - snprintf(logstr, sizeof(logstr), "Outside allowed timespan (time allowed %s)", - check_item->strvalue); - rad_authlog(logstr, request, 1); - - } else if (r > 0) { - - /* - * User is allowed, but set Session-Timeout. - */ - if ((reply_item = pairfind(request->reply->vps, - PW_SESSION_TIMEOUT)) != NULL) { - if (reply_item->lvalue > (unsigned) r) - reply_item->lvalue = r; - } else { - if ((reply_item = paircreate( - PW_SESSION_TIMEOUT, - PW_TYPE_INTEGER)) == NULL) { - radlog(L_ERR|L_CONS, "no memory"); - exit(1); - } - reply_item->lvalue = r; - pairadd(&request->reply->vps, reply_item); - } - } - } - /* * Result should be >= 0 here - if not, it means the user * is rejected, so we overwrite the Post-Auth-Type with diff --git a/src/main/valuepair.c b/src/main/valuepair.c index eebe3d5..403f9ed 100644 --- a/src/main/valuepair.c +++ b/src/main/valuepair.c @@ -599,29 +599,6 @@ static int presufcmp(void *instance, /* - * Compare the current time to a range. - */ -static int timecmp(void *instance, - REQUEST *req, - VALUE_PAIR *request, VALUE_PAIR *check, - VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs) -{ - instance = instance; - request = request; /* shut the compiler up */ - check_pairs = check_pairs; - reply_pairs = reply_pairs; - - /* - * If there's a request, use that timestamp. - */ - if (timestr_match((char *)check->strvalue, - req ? req->timestamp : time(NULL)) >= 0) { - return 0; - } - return -1; -} - -/* * Matches if there is NO SUCH ATTRIBUTE as the one named * in check->strvalue. If there IS such an attribute, it * doesn't match. @@ -666,32 +643,6 @@ static int attrcmp(void *instance, } /* - * Compare the expiration date. - */ -static int expirecmp(void *instance, REQUEST *req UNUSED, - VALUE_PAIR *request, VALUE_PAIR *check, - VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs) -{ - time_t now; - - instance = instance; - request = request; /* shut the compiler up */ - check_pairs = check_pairs; - reply_pairs = reply_pairs; - - /* - * FIXME! This should be request->timestamp! - */ - now = time(NULL); - - if (now <= (signed)check->lvalue) { - return 0; - } - - return +1; -} - -/* * Compare the request packet type. */ static int packetcmp(void *instance UNUSED, REQUEST *req, @@ -733,9 +684,7 @@ void pair_builtincompare_init(void) paircompare_register(PW_PREFIX, PW_USER_NAME, presufcmp, NULL); paircompare_register(PW_SUFFIX, PW_USER_NAME, presufcmp, NULL); paircompare_register(PW_CONNECT_RATE, PW_CONNECT_INFO, connectcmp, NULL); - paircompare_register(PW_CURRENT_TIME, 0, timecmp, NULL); paircompare_register(PW_NO_SUCH_ATTRIBUTE, 0, attrcmp, NULL); - paircompare_register(PW_EXPIRATION, 0, expirecmp, NULL); paircompare_register(PW_PACKET_TYPE, 0, packetcmp, NULL); paircompare_register(PW_RESPONSE_PACKET_TYPE, 0, responsecmp, NULL); } diff --git a/src/modules/rlm_expiration/Makefile b/src/modules/rlm_expiration/Makefile new file mode 100644 index 0000000..77a5aad --- /dev/null +++ b/src/modules/rlm_expiration/Makefile @@ -0,0 +1,4 @@ +TARGET = rlm_expiration +SRCS = rlm_expiration.c + +include ../rules.mak diff --git a/src/modules/rlm_expiration/rlm_expiration.c b/src/modules/rlm_expiration/rlm_expiration.c new file mode 100644 index 0000000..490ae6b --- /dev/null +++ b/src/modules/rlm_expiration/rlm_expiration.c @@ -0,0 +1,225 @@ +/* + * rlm_expiration.c + * + * Version: $Id$ + * + * This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Copyright 2001 The FreeRADIUS server project + * Copyright 2004 Kostas Kalevras + */ + +#include "autoconf.h" +#include "libradius.h" + +#include +#include +#include +#include + +#include "radiusd.h" +#include "modules.h" +#include "conffile.h" + + +static const char rcsid[] = "$Id$"; + +/* + * Define a structure for our module configuration. + * + * These variables do not need to be in a structure, but it's + * a lot cleaner to do so, and a pointer to the structure can + * be used as the instance handle. + */ +typedef struct rlm_expiration_t { + char *msg; /* The Reply-Message passed back to the user if the account is expired */ +} rlm_expiration_t; + +/* + * A mapping of configuration file names to internal variables. + * + * Note that the string is dynamically allocated, so it MUST + * be freed. When the configuration file parse re-reads the string, + * it free's the old one, and strdup's the new one, placing the pointer + * to the strdup'd string into 'config.string'. This gets around + * buffer over-flows. + */ +static CONF_PARSER module_config[] = { + { "reply-message", PW_TYPE_STRING_PTR, offsetof(rlm_expiration_t,msg), NULL, "Password Has Expired\r\n"}, + { NULL, -1, 0, NULL, NULL } +}; + +static int expiration_detach(void *instance); + +/* + * Check if account has expired, and if user may login now. + */ +static int expiration_authorize(void *instance, REQUEST *request) +{ + rlm_expiration_t *data = (rlm_expiration_t *)instance; + VALUE_PAIR *check_item = NULL; + char msg[MAX_STRING_LEN]; + + if ((check_item = pairfind(request->config_items, PW_EXPIRATION)) != NULL){ + /* + * Has this user's password expired? + * + * If so, remove ALL reply attributes, + * and add our own Reply-Message, saying + * why they're being rejected. + */ + DEBUG("rlm_expiration: Checking Expiration time: '%s'",check_item->strvalue); + if (check_item->lvalue < (unsigned) time(NULL)) { + char logstr[MAX_STRING_LEN]; + VALUE_PAIR *module_fmsg_vp; + + DEBUG("rlm_expiration: Account has expired"); + + if (data->msg){ + VALUE_PAIR *vp; + + if (!radius_xlat(msg, sizeof(msg), data->msg, request, NULL)) { + radlog(L_ERR, "rlm_expiration: xlat failed."); + return RLM_MODULE_FAIL; + } + + vp = pairmake("Reply-Message", msg, T_OP_ADD); + pairfree(&request->reply->vps); + request->reply->vps = vp; + } + snprintf(logstr, sizeof(logstr), "Account has expired [Expiration %s]",check_item->strvalue); + module_fmsg_vp = pairmake("Module-Failure-Message", logstr, T_OP_EQ); + pairadd(&request->packet->vps, module_fmsg_vp); + + return RLM_MODULE_USERLOCK; + } + } + else + return RLM_MODULE_NOOP; + + return RLM_MODULE_OK; +} + +/* + * Compare the expiration date. + */ +static int expirecmp(void *instance, REQUEST *req, + VALUE_PAIR *request, VALUE_PAIR *check, + VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs) +{ + time_t now = 0; + instance = instance; + request = request; /* shut the compiler up */ + check_pairs = check_pairs; + reply_pairs = reply_pairs; + + now = (req) ? req->timestamp : time(NULL); + + if (now <= (signed)check->lvalue) + 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 expiration_instantiate(CONF_SECTION *conf, void **instance) +{ + rlm_expiration_t *data; + + /* + * Set up a storage area for instance data + */ + data = rad_malloc(sizeof(*data)); + if (!data) { + radlog(L_ERR, "rlm_expiration: rad_malloc() failed."); + return -1; + } + memset(data, 0, sizeof(*data)); + + /* + * If the configuration parameters can't be parsed, then + * fail. + */ + if (cf_section_parse(conf, data, module_config) < 0) { + free(data); + radlog(L_ERR, "rlm_expiration: Configuration parsing failed."); + return -1; + } + + /* + * If we are passed an empty reply-message don't use it + */ + if (!strlen(data->msg)){ + free(data->msg); + data->msg = NULL; + } + + /* + * Register the expiration comparison operation. + */ + paircompare_register(PW_EXPIRATION, 0, expirecmp, data); + + *instance = data; + + return 0; +} + +static int expiration_detach(void *instance) +{ + rlm_expiration_t *data = (rlm_expiration_t *) instance; + + paircompare_unregister(PW_CURRENT_TIME, expirecmp); + if (data->msg) + free(data->msg); + free(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. + */ +module_t rlm_expiration = { + "Expiration", + RLM_TYPE_THREAD_SAFE, /* type */ + NULL, /* initialization */ + expiration_instantiate, /* instantiation */ + { + NULL, /* authentication */ + expiration_authorize, /* authorization */ + NULL, /* preaccounting */ + NULL, /* accounting */ + NULL, /* checksimul */ + NULL, /* pre-proxy */ + NULL, /* post-proxy */ + NULL /* post-auth */ + }, + expiration_detach, /* detach */ + NULL, /* destroy */ +}; diff --git a/src/modules/rlm_logintime/Makefile b/src/modules/rlm_logintime/Makefile new file mode 100644 index 0000000..0706c20 --- /dev/null +++ b/src/modules/rlm_logintime/Makefile @@ -0,0 +1,4 @@ +TARGET = rlm_logintime +SRCS = rlm_logintime.c timestr.c + +include ../rules.mak diff --git a/src/modules/rlm_logintime/rlm_logintime.c b/src/modules/rlm_logintime/rlm_logintime.c new file mode 100644 index 0000000..e91882f --- /dev/null +++ b/src/modules/rlm_logintime/rlm_logintime.c @@ -0,0 +1,275 @@ +/* + * rlm_logintime.c + * + * Version: $Id$ + * + * This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Copyright 2001 The FreeRADIUS server project + * Copyright 2004 Kostas Kalevras + */ + +#include "autoconf.h" +#include "libradius.h" + +#include +#include +#include +#include + +#include "radiusd.h" +#include "modules.h" +#include "conffile.h" + + +static const char rcsid[] = "$Id$"; + +/* + * Define a structure for our module configuration. + * + * These variables do not need to be in a structure, but it's + * a lot cleaner to do so, and a pointer to the structure can + * be used as the instance handle. + */ +typedef struct rlm_logintime_t { + char *msg; /* The Reply-Message passed back to the user + * if the account is outside allowed timestamp */ + int min_time; +} rlm_logintime_t; + +/* + * A mapping of configuration file names to internal variables. + * + * Note that the string is dynamically allocated, so it MUST + * be freed. When the configuration file parse re-reads the string, + * it free's the old one, and strdup's the new one, placing the pointer + * to the strdup'd string into 'config.string'. This gets around + * buffer over-flows. + */ +static CONF_PARSER module_config[] = { + { "reply-message", PW_TYPE_STRING_PTR, offsetof(rlm_logintime_t,msg), NULL, + "You are calling outside your allowed timespan\r\n"}, + { "minimum-timeout", PW_TYPE_INTEGER, offsetof(rlm_logintime_t,min_time), NULL, "60" }, + { NULL, -1, 0, NULL, NULL } +}; + +static int logintime_detach(void *instance); + +/* + * Compare the current time to a range. + */ +static int timecmp(void *instance, + REQUEST *req, + VALUE_PAIR *request, VALUE_PAIR *check, + VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs) +{ + instance = instance; + request = request; /* shut the compiler up */ + check_pairs = check_pairs; + reply_pairs = reply_pairs; + + /* + * If there's a request, use that timestamp. + */ + if (timestr_match((char *)check->strvalue, + req ? req->timestamp : time(NULL)) >= 0) + return 0; + + return -1; +} + +/* + * Check if account has expired, and if user may login now. + */ +static int logintime_authorize(void *instance, REQUEST *request) +{ + rlm_logintime_t *data = (rlm_logintime_t *)instance; + VALUE_PAIR *check_item = NULL; + int r; + + if ((check_item = pairfind(request->config_items, PW_LOGIN_TIME)) != NULL) { + + /* + * Authentication is OK. Now see if this + * user may login at this time of the day. + */ + DEBUG("rlm_logintime: Checking Login-Time: '%s'",check_item->strvalue); + r = timestr_match((char *)check_item->strvalue, + request->timestamp); + if (r == 0) { /* unlimited */ + /* + * Do nothing: login-time is OK. + */ + + /* + * Session-Timeout needs to be at least + * 60 seconds, some terminal servers + * ignore smaller values. + */ + DEBUG("rlm_logintime: timestr returned unlimited"); + } else if (r < data->min_time) { + char logstr[MAX_STRING_LEN]; + VALUE_PAIR *module_fmsg_vp; + + /* + * User called outside allowed time interval. + */ + + DEBUG("rlm_logintime: timestr returned reject"); + if (data->msg){ + char msg[MAX_STRING_LEN]; + VALUE_PAIR *tmp; + + if (!radius_xlat(msg, sizeof(msg), data->msg, request, NULL)) { + radlog(L_ERR, "rlm_logintime: xlat failed."); + return RLM_MODULE_FAIL; + } + pairfree(&request->reply->vps); + tmp = pairmake("Reply-Message", msg, T_OP_SET); + request->reply->vps = tmp; + } + + snprintf(logstr, sizeof(logstr), "Outside allowed timespan (time allowed %s)", + check_item->strvalue); + module_fmsg_vp = pairmake("Module-Failure-Message", logstr, T_OP_EQ); + pairadd(&request->packet->vps, module_fmsg_vp); + + return RLM_MODULE_REJECT; + + } else if (r > 0) { + VALUE_PAIR *reply_item; + + /* + * User is allowed, but set Session-Timeout. + */ + DEBUG("rlm_logintime: timestr returned accept"); + if ((reply_item = pairfind(request->reply->vps, PW_SESSION_TIMEOUT)) != NULL) { + if (reply_item->lvalue > (unsigned) r) + reply_item->lvalue = r; + } else { + if ((reply_item = paircreate( PW_SESSION_TIMEOUT, PW_TYPE_INTEGER)) == NULL) { + radlog(L_ERR|L_CONS, "no memory"); + return RLM_MODULE_FAIL; + } + reply_item->lvalue = r; + pairadd(&request->reply->vps, reply_item); + } + DEBUG("rlm_logintime: Session-Timeout set to: %d",r); + } + } + else + return RLM_MODULE_NOOP; + + return RLM_MODULE_OK; +} + + +/* + * 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 logintime_instantiate(CONF_SECTION *conf, void **instance) +{ + rlm_logintime_t *data; + + /* + * Set up a storage area for instance data + */ + data = rad_malloc(sizeof(*data)); + if (!data) { + radlog(L_ERR, "rlm_logintime: rad_malloc() failed."); + return -1; + } + memset(data, 0, sizeof(*data)); + + /* + * If the configuration parameters can't be parsed, then + * fail. + */ + if (cf_section_parse(conf, data, module_config) < 0) { + free(data); + radlog(L_ERR, "rlm_logintime: Configuration parsing failed."); + return -1; + } + + /* + * If we are passed an empty reply-message don't use it + */ + if (!strlen(data->msg)){ + free(data->msg); + data->msg = NULL; + } + + if (data->min_time == 0){ + radlog(L_ERR, "rlm_logintime: Minimum timeout should be non zero."); + free(data->msg); + free(data); + return -1; + } + + /* + * Register a Current-Time comparison function + */ + paircompare_register(PW_CURRENT_TIME, 0, timecmp, data); + + *instance = data; + + return 0; +} + +static int logintime_detach(void *instance) +{ + rlm_logintime_t *data = (rlm_logintime_t *) instance; + + paircompare_unregister(PW_CURRENT_TIME, timecmp); + if (data->msg) + free(data->msg); + free(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. + */ +module_t rlm_logintime = { + "Login Time", + RLM_TYPE_THREAD_SAFE, /* type */ + NULL, /* initialization */ + logintime_instantiate, /* instantiation */ + { + NULL, /* authentication */ + logintime_authorize, /* authorization */ + NULL, /* preaccounting */ + NULL, /* accounting */ + NULL, /* checksimul */ + NULL, /* pre-proxy */ + NULL, /* post-proxy */ + NULL /* post-auth */ + }, + logintime_detach, /* detach */ + NULL, /* destroy */ +}; diff --git a/src/main/timestr.c b/src/modules/rlm_logintime/timestr.c similarity index 100% rename from src/main/timestr.c rename to src/modules/rlm_logintime/timestr.c diff --git a/src/modules/stable b/src/modules/stable index 39fa68b..698504e 100644 --- a/src/modules/stable +++ b/src/modules/stable @@ -11,12 +11,14 @@ rlm_detail rlm_digest rlm_eap rlm_exec +rlm_expiration rlm_expr rlm_fastusers rlm_files rlm_ippool rlm_krb5 rlm_ldap +rlm_logintime rlm_mschap rlm_ns_mta_md5 rlm_pam -- 2.1.4