diff options
Diffstat (limited to 'src/modules/rlm_date')
-rw-r--r-- | src/modules/rlm_date/README.md | 9 | ||||
-rw-r--r-- | src/modules/rlm_date/all.mk | 2 | ||||
-rw-r--r-- | src/modules/rlm_date/rlm_date.c | 141 |
3 files changed, 152 insertions, 0 deletions
diff --git a/src/modules/rlm_date/README.md b/src/modules/rlm_date/README.md new file mode 100644 index 0000000..2145c2f --- /dev/null +++ b/src/modules/rlm_date/README.md @@ -0,0 +1,9 @@ +# rlm_date +## Metadata +<dl> + <dt>category</dt><dd>policy</dd> +</dl> + +## Summary + +Converts date strings between user configurable formats. diff --git a/src/modules/rlm_date/all.mk b/src/modules/rlm_date/all.mk new file mode 100644 index 0000000..94c83a6 --- /dev/null +++ b/src/modules/rlm_date/all.mk @@ -0,0 +1,2 @@ +TARGET := rlm_date.a +SOURCES := rlm_date.c diff --git a/src/modules/rlm_date/rlm_date.c b/src/modules/rlm_date/rlm_date.c new file mode 100644 index 0000000..79191e7 --- /dev/null +++ b/src/modules/rlm_date/rlm_date.c @@ -0,0 +1,141 @@ +/* + * 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 + */ + +/** + * @file rlm_date.c + * @brief Translates timestrings between formats. + * + * @author Artur Malinowski <artur@wow.com> + * + * @copyright 2013 Artur Malinowski <artur@wow.com> + * @copyright 1999-2013 The FreeRADIUS Server Project. + */ + +#include <freeradius-devel/radiusd.h> +#include <freeradius-devel/modules.h> +#include <ctype.h> +#include <time.h> + +typedef struct rlm_date_t { + char const *xlat_name; + char const *fmt; + bool utc; +} rlm_date_t; + +static const CONF_PARSER module_config[] = { + { "format", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_date_t, fmt), "%b %e %Y %H:%M:%S %Z" }, + { "utc", FR_CONF_OFFSET(PW_TYPE_BOOLEAN, rlm_date_t, utc), "no" }, + CONF_PARSER_TERMINATOR +}; + +DIAG_OFF(format-nonliteral) +static ssize_t xlat_date_convert(void *instance, REQUEST *request, char const *fmt, char *out, size_t outlen) +{ + rlm_date_t *inst = instance; + time_t date = 0; + struct tm tminfo; + VALUE_PAIR *vp; + + memset(&tminfo, 0, sizeof(tminfo)); + + if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) { + *out = '\0'; + return 0; + } + + switch (vp->da->type) { + /* + * These are 'to' types, i.e. we'll convert the integers + * to a time structure, and then output it in the specified + * format as a string. + */ + case PW_TYPE_DATE: + date = vp->vp_date; + goto encode; + + case PW_TYPE_INTEGER: + case PW_TYPE_INTEGER64: + date = (time_t) vp->vp_integer; + + encode: + if (!inst->utc) { + if (localtime_r(&date, &tminfo) == NULL) { + REDEBUG("Failed converting time string to localtime"); + goto error; + } + } else { + if (gmtime_r(&date, &tminfo) == NULL) { + REDEBUG("Failed converting time string to gmtime"); + goto error; + } + } + return strftime(out, outlen, inst->fmt, &tminfo); + + /* + * These are 'from' types, i.e. we'll convert the input string + * into a time structure, and then output it as an integer + * unix timestamp. + */ + case PW_TYPE_STRING: + if (strptime(vp->vp_strvalue, inst->fmt, &tminfo) == NULL) { + REDEBUG("Failed to parse time string \"%s\" as format '%s'", vp->vp_strvalue, inst->fmt); + goto error; + } + + if (!inst->utc) { + date = mktime(&tminfo); + } else { + date = timegm(&tminfo); + } + if (date < 0) { + REDEBUG("Failed converting parsed time into unix time"); + + } + return snprintf(out, outlen, "%" PRIu64, (uint64_t) date); + + default: + REDEBUG("Can't convert type %s into date", fr_int2str(dict_attr_types, vp->da->type, "<INVALID>")); + } + + error: + *out = '\0'; + return -1; +} +DIAG_ON(format-nonliteral) + +static int mod_bootstrap(CONF_SECTION *conf, void *instance) +{ + rlm_date_t *inst = instance; + + inst->xlat_name = cf_section_name2(conf); + if (!inst->xlat_name) { + inst->xlat_name = cf_section_name1(conf); + } + + xlat_register(inst->xlat_name, xlat_date_convert, NULL, inst); + + return 0; +} + +extern module_t rlm_date; +module_t rlm_date = { + .magic = RLM_MODULE_INIT, + .name = "date", + .inst_size = sizeof(rlm_date_t), + .config = module_config, + .bootstrap = mod_bootstrap +}; + |