#include <freeradius-devel/ident.h>
RCSID("$Id$")
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
#include <ctype.h>
typedef struct rlm_logintime_t {
char *msg;
int min_time;
} rlm_logintime_t;
static const 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);
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;
check_pairs = check_pairs;
reply_pairs = reply_pairs;
if (timestr_match((char *)check->vp_strvalue,
req ? req->timestamp : time(NULL)) >= 0)
return 0;
return -1;
}
static int time_of_day(void *instance,
REQUEST *req,
VALUE_PAIR *request, VALUE_PAIR *check,
VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs)
{
int scan;
int hhmmss, when;
char *p;
struct tm *tm, s_tm;
instance = instance;
request = request;
check_pairs = check_pairs;
reply_pairs = reply_pairs;
if (!req) return -1;
if (strspn(check->vp_strvalue, "0123456789: ") != strlen(check->vp_strvalue)) {
DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
check->vp_strvalue);
return -1;
}
tm = localtime_r(&req->timestamp, &s_tm);
hhmmss = (tm->tm_hour * 3600) + (tm->tm_min * 60) + tm->tm_sec;
p = check->vp_strvalue;
scan = atoi(p);
p = strchr(p, ':');
if ((scan > 23) || !p) {
DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
check->vp_strvalue);
return -1;
}
when = scan * 3600;
p++;
scan = atoi(p);
if (scan > 59) {
DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
check->vp_strvalue);
return -1;
}
when += scan * 60;
p = strchr(p, ':');
if (p) {
scan = atoi(p + 1);
if (scan > 59) {
DEBUG("rlm_logintime: Bad Time-Of-Day value \"%s\"",
check->vp_strvalue);
return -1;
}
when += scan;
}
fprintf(stderr, "returning %d - %d\n",
hhmmss, when);
return hhmmss - when;
}
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) {
DEBUG("rlm_logintime: Checking Login-Time: '%s'",check_item->vp_strvalue);
r = timestr_match((char *)check_item->vp_strvalue,
request->timestamp);
if (r == 0) {
DEBUG("rlm_logintime: timestr returned unlimited");
} else if (r < data->min_time) {
char logstr[MAX_STRING_LEN];
VALUE_PAIR *module_fmsg_vp;
DEBUG("rlm_logintime: timestr returned reject");
if (data->msg && data->msg[0]){
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->vp_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;
DEBUG("rlm_logintime: timestr returned accept");
if ((reply_item = pairfind(request->reply->vps, PW_SESSION_TIMEOUT)) != NULL) {
if (reply_item->vp_integer > (unsigned) r)
reply_item->vp_integer = r;
} else {
reply_item = radius_paircreate(request,
&request->reply->vps,
PW_SESSION_TIMEOUT,
PW_TYPE_INTEGER);
reply_item->vp_integer = r;
}
DEBUG("rlm_logintime: Session-Timeout set to: %d",r);
}
}
else
return RLM_MODULE_NOOP;
return RLM_MODULE_OK;
}
static int logintime_instantiate(CONF_SECTION *conf, void **instance)
{
rlm_logintime_t *data;
data = rad_malloc(sizeof(*data));
if (!data) {
radlog(L_ERR, "rlm_logintime: rad_malloc() failed.");
return -1;
}
memset(data, 0, sizeof(*data));
if (cf_section_parse(conf, data, module_config) < 0) {
free(data);
radlog(L_ERR, "rlm_logintime: Configuration parsing failed.");
return -1;
}
if (data->min_time == 0){
radlog(L_ERR, "rlm_logintime: Minimum timeout should be non zero.");
free(data);
return -1;
}
paircompare_register(PW_CURRENT_TIME, 0, timecmp, data);
paircompare_register(PW_TIME_OF_DAY, 0, time_of_day, data);
*instance = data;
return 0;
}
static int logintime_detach(void *instance)
{
paircompare_unregister(PW_CURRENT_TIME, timecmp);
paircompare_unregister(PW_TIME_OF_DAY, time_of_day);
free(instance);
return 0;
}
module_t rlm_logintime = {
RLM_MODULE_INIT,
"logintime",
RLM_TYPE_CHECK_CONFIG_SAFE,
logintime_instantiate,
logintime_detach,
{
NULL,
logintime_authorize,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
},
};