25 RCSID(
"$Id: b0f34c57fb69956828d32446274517a876d2e4db $")
28 #include <freeradius-devel/radiusd.h>
29 #include <freeradius-devel/md5.h>
30 #include <freeradius-devel/sha1.h>
31 #include <freeradius-devel/base64.h>
32 #include <freeradius-devel/modules.h>
33 #include <freeradius-devel/rad_assert.h>
35 #ifdef HAVE_OPENSSL_EVP_H
36 # include <openssl/evp.h>
60 static char randstr_salt[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmopqrstuvwxyz/.";
66 static char randstr_otp[] =
"469ACGHJKLMNPQRUVWXYabdfhijkprstuvwxyz";
68 static char const hextab[] =
"0123456789abcdef";
79 static int64_t
fr_pow(int64_t base, int64_t exp)
81 static const uint8_t highest_bit_set[] = {
82 0, 1, 2, 2, 3, 3, 3, 3,
83 4, 4, 4, 4, 4, 4, 4, 4,
84 5, 5, 5, 5, 5, 5, 5, 5,
85 5, 5, 5, 5, 5, 5, 5, 5,
86 6, 6, 6, 6, 6, 6, 6, 6,
87 6, 6, 6, 6, 6, 6, 6, 6,
88 6, 6, 6, 6, 6, 6, 6, 6,
89 6, 6, 6, 6, 6, 6, 6, 6
100 return 1 - 2 * (exp & 1);
105 switch (highest_bit_set[exp]) {
107 if (exp & 1) result *= base;
111 if (exp & 1) result *= base;
115 if (exp & 1) result *= base;
119 if (exp & 1) result *= base;
123 if (exp & 1) result *= base;
127 if (exp & 1) result *= base;
188 bool negative =
false;
189 char const *p = *string;
194 while (isspace((
int) *p)) p++;
210 if ((*p ==
'0') && (p[1] ==
'x')) {
213 x = strtoul(p, &end, 16);
242 RWDEBUG(
"Can't find &%.*s. Using 0 as operand value", (
int)vpt.
len, vpt.
name);
251 REDEBUG(
"Failed converting &%.*s to an integer value: %s", (
int) vpt.
len,
255 if (value.integer64 > INT64_MAX) {
257 REDEBUG(
"Value of &%.*s (%"PRIu64
") would overflow a signed 64bit integer "
258 "(our internal arithmetic type)", (
int)vpt.
len, vpt.
name, value.integer64);
261 x = (int64_t)value.integer64;
267 if (vp->vp_integer64 > INT64_MAX)
goto overflow;
268 x = (int64_t)vp->vp_integer64;
282 RDEBUG(
"No trailing ')'");
289 if ((*p <
'0') || (*p >
'9')) {
290 RDEBUG2(
"Not a number at \"%s\"", p);
299 while ((*p >=
'0') && (*p <=
'9')) {
308 if (negative) x = -x;
329 RDEBUG(
"Division by zero!");
338 RDEBUG(
"Division by zero!");
351 RDEBUG(
"Shift must be less than 63 (was %lld)", (
long long int) rhs);
355 *answer = lhs << rhs;
360 RDEBUG(
"Shift must be less than 63 (was %lld)", (
long long int) rhs);
364 *answer = lhs >> rhs;
377 REDEBUG(
"Exponent must be between 0-63 (was %lld)", (
long long int) rhs);
382 REDEBUG(
"Base must be between 0-65535 (was %lld)", (
long long int) lhs);
386 *answer =
fr_pow(lhs, rhs);
396 char const *p = *string;
402 if (*p == map[i].op) {
409 if ((p[0] ==
'<') && (p[1] ==
'<')) {
415 if ((p[0] ==
'>') && (p[1] ==
'>')) {
421 RDEBUG(
"Expected operator at \"%s\"", p);
429 char const *p, *op_p;
434 if (!
get_number(request, &p, &lhs))
return false;
437 while (isspace((
int) *p)) p++;
442 if (!*p || (*p ==
')')) {
461 if (precedence[
this] <= precedence[prev]) {
472 if (!
calc_result(request, lhs,
this, rhs, answer))
return false;
490 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
491 REQUEST *request,
char const *fmt)
503 RDEBUG(
"Invalid text after expression: %s", p);
507 snprintf(*out, outlen,
"%lld", (
long long int) result);
515 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
525 if (result <= 0)
return -1;
526 if (result >= (1 << 30)) result = (1 << 30);
531 snprintf(*out, outlen,
"%ld", (
long int) result);
541 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
548 size_t freespace = outlen;
550 if (outlen <= 1)
return 0;
553 while (*p && (--freespace > 0)) {
562 while (isdigit((
int) *p)) {
581 *out_p++ =
'a' + (result % 26);
588 *out_p++ =
'A' + (result % 26);
595 *out_p++ =
'0' + (result % 10);
602 *out_p++ = randstr_salt[result % (
sizeof(
randstr_salt) - 3)];
609 *out_p++ = randstr_punc[result % (
sizeof(
randstr_punc) - 1)];
616 *out_p++ =
'!' + (result % 95);
623 *out_p++ = randstr_salt[result % (
sizeof(
randstr_salt) - 1)];
631 *out_p++ = randstr_otp[result % (
sizeof(
randstr_otp) - 1)];
643 snprintf(out_p, 3,
"%02x", result % 256);
658 snprintf(out_p, 3,
"%02X", result % 256);
666 ERROR(
"rlm_expr: invalid character class '%c'", *p);
681 return outlen - freespace;
689 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
694 size_t freespace = outlen;
696 if (outlen <= 1)
return 0;
699 while (*p && (--freespace > 0)) {
718 snprintf(out_p, 4,
"%%%02X", (uint8_t) *p++);
728 return outlen - freespace;
738 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
739 REQUEST *request,
char const *fmt)
744 size_t freespace = outlen;
746 if (outlen <= 1)
return 0;
749 while (*p && (--freespace > 0)) {
757 if (!(c1 = memchr(hextab, tolower(*++p), 16)) ||
758 !(c2 = memchr(hextab, tolower(*++p), 16))) {
759 REMARKER(fmt, p - fmt,
"Non-hex char in % sequence");
768 return outlen - freespace;
776 void const *mod_inst,
UNUSED void const *xlat_inst,
782 size_t freespace = outlen;
792 if (freespace <= (
size_t)(1 + (chr_len * 3)))
break;
796 ret =
snprintf(out_p, freespace,
"=%02X=%02X=%02X=%02X",
797 (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3]);
801 ret =
snprintf(out_p, freespace,
"=%02X=%02X=%02X",
802 (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2]);
806 ret =
snprintf(out_p, freespace,
"=%02X=%02X", (uint8_t)p[0], (uint8_t)p[1]);
810 ret =
snprintf(out_p, freespace,
"=%02X", (uint8_t)p[0]);
823 if (freespace <= 1)
break;
828 memcpy(out_p, p, chr_len);
831 freespace -= chr_len;
835 return outlen - freespace;
843 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
849 size_t freespace = outlen;
851 if (outlen <= 1)
return 0;
854 while (*p && (--freespace > 0)) {
864 if (!(c1 = memchr(hextab, tolower(*(p + 1)), 16)) ||
865 !(c2 = memchr(hextab, tolower(*(p + 2)), 16)))
goto next;
874 return outlen - freespace;
883 static ssize_t
lc_xlat(
char **out,
size_t outlen,
884 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
890 if (outlen <= 1)
return 0;
892 for (p = fmt, q = *out; *p !=
'\0'; p++, outlen--) {
893 if (outlen <= 1)
break;
895 *(q++) = tolower((
int) *p);
909 static ssize_t
uc_xlat(
char **out,
size_t outlen,
910 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
916 if (outlen <= 1)
return 0;
918 for (p = fmt, q = *out; *p !=
'\0'; p++, outlen--) {
919 if (outlen <= 1)
break;
921 *(q++) = toupper((
int) *p);
934 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
935 REQUEST *request,
char const *fmt)
938 ssize_t i, len, inlen;
943 if (inlen < 0)
return -1;
953 len = (outlen / 2) - 1;
954 if (len > 16) len = 16;
956 for (i = 0; i < len; i++)
snprintf((*out) + (i * 2), 3,
"%02x", digest[i]);
966 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
967 REQUEST *request,
char const *fmt)
970 ssize_t i, len, inlen;
975 if (inlen < 0)
return -1;
985 len = (outlen / 2) - 1;
986 if (len > 20) len = 20;
988 for (i = 0; i < len; i++)
snprintf((*out) + (i * 2), 3,
"%02x", digest[i]);
997 #ifdef HAVE_OPENSSL_EVP_H
998 static ssize_t evp_md_xlat(
char **out,
size_t outlen,
999 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1000 REQUEST *request,
char const *fmt, EVP_MD
const *md)
1002 uint8_t digest[EVP_MAX_MD_SIZE];
1003 unsigned int digestlen, i, len;
1010 if (inlen < 0)
return -1;
1012 ctx = EVP_MD_CTX_create();
1013 EVP_DigestInit_ex(ctx, md, NULL);
1014 EVP_DigestUpdate(ctx, p, inlen);
1015 EVP_DigestFinal_ex(ctx, digest, &digestlen);
1016 EVP_MD_CTX_destroy(ctx);
1022 len = (outlen / 2) - 1;
1023 if (len > digestlen) len = digestlen;
1025 for (i = 0; i < len; i++)
snprintf((*out) + (i * 2), 3,
"%02x", digest[i]);
1027 return strlen(*out);
1030 # define EVP_MD_XLAT(_md) \
1031 static ssize_t _md##_xlat(char **out, size_t outlen,\
1032 void const *mod_inst, void const *xlat_inst,\
1033 REQUEST *request, char const *fmt)\
1035 return evp_md_xlat(out, outlen, mod_inst, xlat_inst, request, fmt, EVP_##_md());\
1047 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1048 REQUEST *request,
char const *fmt)
1050 uint8_t
const *
data, *key;
1052 ssize_t data_len, key_len;
1056 if (outlen <= (
sizeof(digest) * 2)) {
1057 REDEBUG(
"Insufficient space to write digest, needed %zu bytes, have %zu bytes",
1058 (
sizeof(digest) * 2) + 1, outlen);
1062 p = strchr(fmt,
' ');
1064 REDEBUG(
"HMAC requires exactly two arguments (&data &key)");
1068 if ((
size_t)(p - fmt) >=
sizeof(data_ref)) {
1069 REDEBUG(
"Insufficient space to store HMAC input data, needed %zu bytes, have %zu bytes",
1070 (p - fmt) + 1,
sizeof(data_ref));
1074 strlcpy(data_ref, fmt, (p - fmt) + 1);
1077 if (data_len < 0)
return -1;
1079 while (isspace(*p) && p++);
1082 if (key_len < 0)
return -1;
1084 fr_hmac_md5(digest, data, data_len, key, key_len);
1086 return fr_bin2hex(*out, digest,
sizeof(digest));
1094 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1095 REQUEST *request,
char const *fmt)
1097 uint8_t
const *
data, *key;
1099 ssize_t data_len, key_len;
1103 if (outlen <= (
sizeof(digest) * 2)) {
1104 REDEBUG(
"Insufficient space to write digest, needed %zu bytes, have %zu bytes",
1105 (
sizeof(digest) * 2) + 1, outlen);
1109 p = strchr(fmt,
' ');
1111 REDEBUG(
"HMAC requires exactly two arguments (&data &key)");
1115 if ((
size_t)(p - fmt) >=
sizeof(data_ref)) {
1116 REDEBUG(
"Insufficient space to store HMAC input data, needed %zu bytes, have %zu bytes",
1117 (p - fmt) + 1,
sizeof(data_ref));
1121 strlcpy(data_ref, fmt, (p - fmt) + 1);
1124 if (data_len < 0)
return -1;
1126 while (isspace(*p) && p++);
1129 if (key_len < 0)
return -1;
1133 return fr_bin2hex(*out, digest,
sizeof(digest));
1144 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1145 REQUEST *request,
char const *fmt)
1149 size_t len, freespace = outlen;
1170 REDEBUG(
"Insufficient space to store pair string, needed %zu bytes have %zu bytes",
1171 (p - *out) + len, outlen);
1177 if (freespace < 2) {
1188 if (p != *out) p -= 2;
1199 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1200 REQUEST *request,
char const *fmt)
1227 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1228 REQUEST *request,
char const *fmt)
1230 uint8_t decbuf[1024];
1233 ssize_t len = strlen(fmt);
1237 REDEBUG(
"Base64 string invalid");
1241 if ((
size_t)((declen * 2) + 1) > outlen) {
1242 REDEBUG(
"Base64 conversion failed, output buffer exhausted, needed %zd bytes, have %zd bytes",
1243 (declen * 2) + 1, outlen);
1257 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1258 REQUEST *request,
char const *fmt)
1265 char const *p = fmt;
1271 while (isspace(*p) && p++);
1283 REDEBUG(
"explode needs exactly two arguments: &ref <delim>");
1287 if (*p ==
'\0')
goto arg_error;
1314 end = p + vp->vp_length;
1316 q = memchr(p, delim, end - p);
1319 if (p == vp->
data.ptr)
goto next;
1341 buff = talloc_array(
new, uint8_t, q - p);
1342 memcpy(buff, p, q - p);
1351 buff = talloc_array(
new,
char, (q - p) + 1);
1352 memcpy(buff, p, q - p);
1381 return snprintf(*out, outlen,
"%i", count);
1394 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1395 REQUEST *request,
char const *fmt)
1402 struct tm *local, local_buff;
1409 num = strtoul(p, &q, 10);
1410 if (!q || *q ==
'\0') {
1411 REDEBUG(
"nexttime: <int> must be followed by period specifier (h|d|w|m|y)");
1426 local->tm_hour += num;
1431 local->tm_mday += num;
1436 local->tm_mday += (7 - local->tm_wday) + (7 * (num-1));
1442 local->tm_mon += num;
1449 local->tm_year += num;
1453 REDEBUG(
"nexttime: Invalid period specifier '%c', must be h|d|w|m|y", *p);
1457 return snprintf(*out, outlen,
"%" PRIu64, (uint64_t)(mktime(local) - now));
1477 while (isspace((
int) *p)) p++;
1480 RDEBUG(
"First argument must be an attribute reference");
1485 if (!vpt)
return false;
1496 while (isspace((
int) *p)) p++;
1498 length = strtoul(p, &end, 10);
1499 if ((length == ULONG_MAX) || (length > 8192)) {
1501 RDEBUG(
"Invalid length found at: %s", p);
1516 RDEBUG(
"Invalid text found at: %s", p);
1520 while (isspace((
int) *p)) p++;
1524 RDEBUG(
"Invalid text found at: %s", p);
1543 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1544 REQUEST *request,
char const *fmt)
1551 if (!
parse_pad(request, fmt, &vpt, &pad, &fill))
return 0;
1553 if (outlen <= pad) {
1554 RWARN(
"Output is too short! Result will be truncated");
1562 len =
tmpl_expand(NULL, *out, pad + 1, request, vpt, NULL, NULL);
1563 if (len <= 0)
return 0;
1565 if ((
size_t) len >= pad)
return pad;
1571 memmove((*out) + (pad - len), *out, len + 1);
1572 memset(*out, fill, pad - len);
1583 UNUSED void const *mod_inst,
UNUSED void const *xlat_inst,
1584 REQUEST *request,
char const *fmt)
1591 if (!
parse_pad(request, fmt, &vpt, &pad, &fill))
return 0;
1593 if (outlen <= pad) {
1594 RWARN(
"Output is too short! Result will be truncated");
1602 len =
tmpl_expand(NULL, *out, pad + 1, request, vpt, NULL, NULL);
1603 if (len <= 0)
return 0;
1605 if ((
size_t) len >= pad)
return pad;
1610 memset((*out) + len, fill, pad - len);
1648 #ifdef HAVE_OPENSSL_EVP_H
1686 .config = module_config,
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
void fr_sha1_update(fr_sha1_ctx *context, uint8_t const *data, size_t len)
ssize_t tmpl_expand(char const **out, char *buff, size_t outlen, REQUEST *request, vp_tmpl_t const *vpt, xlat_escape_t escape, void *escape_ctx)
Expand a vp_tmpl_t to a string writing the result to a buffer.
#define RINDENT()
Indent R* messages by one level.
int xlat_register(void *mod_inst, char const *name, xlat_func_t func, xlat_escape_t escape, xlat_instantiate_t instantiate, size_t inst_size, size_t buf_len)
Register an xlat function.
Metadata exported by the module.
char const * name
Raw string used to create the template.
uint32_t fr_rand(void)
Return a 32-bit random number.
#define SHA1_DIGEST_LENGTH
#define FR_BASE64_ENC_LENGTH(inlen)
static ssize_t sha1_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Calculate the SHA1 hash of a string or attribute.
static ssize_t uc_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, char const *fmt)
Convert a string to uppercase.
#define REMARKER(_m, _i, _e)
Output string with error marker, showing where format error occurred.
ssize_t tmpl_from_attr_substr(vp_tmpl_t *vpt, char const *name, request_refs_t request_def, pair_lists_t list_def, bool allow_unknown, bool allow_undefined)
Parse a string into a TMPL_TYPE_ATTR_* or TMPL_TYPE_LIST type vp_tmpl_t.
int8_t tag
Tag value used to group valuepairs.
void fr_md5_init(FR_MD5_CTX *ctx)
Initialise a new MD5 context.
#define CONF_PARSER_TERMINATOR
static ssize_t urlquote_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, char const *fmt)
URLencode special characters.
static char randstr_punc[]
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
#define XLAT_DEFAULT_BUF_LEN
ssize_t fr_base64_decode(uint8_t *out, size_t outlen, char const *in, size_t inlen)
Defines a CONF_PAIR to C data type mapping.
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
static int64_t fr_pow(int64_t base, int64_t exp)
Calculate powers.
void fr_sha1_init(fr_sha1_ctx *context)
static ssize_t hmac_sha1_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Generate the HMAC-SHA1 of a string or attribute.
static bool parse_pad(REQUEST *request, char const *fmt, vp_tmpl_t **pvpt, size_t *plength, char *fill)
void fr_md5_update(FR_MD5_CTX *ctx, uint8_t const *in, size_t inlen) CC_BOUNDED(__string__
#define is_truncated(_ret, _max)
void fr_pair_value_strsteal(VALUE_PAIR *vp, char const *src)
Reparent an allocated char buffer to a VALUE_PAIR.
static ssize_t hmac_md5_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Calculate any digest supported by OpenSSL EVP_MD.
static bool get_expression(REQUEST *request, char const **string, int64_t *answer, expr_token_t prev)
static bool get_number(REQUEST *request, char const **string, int64_t *answer)
static ssize_t explode_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Split an attribute into multiple new attributes based on a delimiter.
VALUE_PAIR * tmpl_cursor_init(int *err, vp_cursor_t *cursor, REQUEST *request, vp_tmpl_t const *vpt)
Initialise a vp_cursor_t to the VALUE_PAIR specified by a vp_tmpl_t.
static ssize_t rpad_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
right pad a string
int value_data_cast(TALLOC_CTX *ctx, value_data_t *dst, PW_TYPE dst_type, fr_dict_attr_t const *dst_enumv, PW_TYPE src_type, fr_dict_attr_t const *src_enumv, value_data_t const *src)
Convert one type of value_data_t to another.
int tmpl_find_vp(VALUE_PAIR **out, REQUEST *request, vp_tmpl_t const *vpt)
Returns the first VP matching a vp_tmpl_t.
void fr_hmac_md5(uint8_t digest[MD5_DIGEST_LENGTH], uint8_t const *text, size_t text_len, uint8_t const *key, size_t key_len) CC_BOUNDED(__minbytes__
void fr_cursor_merge(vp_cursor_t *cursor, VALUE_PAIR *vp)
Merges multiple VALUE_PAIR into the cursor.
ssize_t tmpl_from_attr_str(vp_tmpl_t *vpt, char const *name, request_refs_t request_def, pair_lists_t list_def, bool allow_unknown, bool allow_undefined)
Parse a string into a TMPL_TYPE_ATTR_* or TMPL_TYPE_LIST type vp_tmpl_t.
void fr_cursor_insert(vp_cursor_t *cursor, VALUE_PAIR *vp)
Insert a single VALUE_PAIR at the end of the list.
static ssize_t lpad_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
left pad a string
Attributes in incoming or internally proxied request.
static bool calc_result(REQUEST *request, int64_t lhs, expr_token_t op, int64_t rhs, int64_t *answer)
static ssize_t pairs_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Encode attributes as a series of string attribute/value pairs.
static ssize_t base64_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Encode string or attribute as base64.
Stores an attribute, a value and various bits of other data.
void fr_sha1_final(uint8_t digest[20], fr_sha1_ctx *context)
USES_APPLE_DEPRECATED_API struct rlm_expr_t rlm_expr_t
static ssize_t escape_xlat(char **out, size_t outlen, void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, char const *fmt)
Equivalent to the old safe_characters functionality in rlm_sql but with utf8 support.
static int precedence[TOKEN_LAST+1]
#define REXDENT()
Exdent (unindent) R* messages by one level.
FR_TOKEN op
Operator to use when moving or inserting valuepair into a list.
char const * fr_strerror(void)
Get the last library error.
size_t len
Length of the raw string used to create the template.
char const * cf_section_name1(CONF_SECTION const *cs)
char const * fr_utf8_strchr(int *chr_len, char const *str, char const *chr)
Return a pointer to the first UTF8 char in a string.
static ssize_t urlunquote_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
URLdecode special characters.
static ssize_t base64_to_hex_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Convert base64 to hex.
static ssize_t md5_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Calculate the MD5 hash of a string or attribute.
uint64_t magic
Used to validate module struct.
void fr_pair_value_memsteal(VALUE_PAIR *vp, uint8_t const *src)
Reparent an allocated octet buffer to a VALUE_PAIR.
static int mod_bootstrap(CONF_SECTION *conf, void *instance)
size_t fr_base64_encode(char *out, size_t outlen, uint8_t const *in, size_t inlen)
Base 64 encode binary data.
#define FR_CONF_OFFSET(_n, _t, _s, _f)
ssize_t xlat_fmt_to_ref(uint8_t const **out, REQUEST *request, char const *fmt)
Crappy temporary function to add attribute ref support to xlats.
void pair_builtincompare_add(void *instance)
static ssize_t randstr_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, char const *fmt)
Generate a string of random chars.
static char const hextab[]
static ssize_t rand_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, char const *fmt)
Generate a random integer value.
static ssize_t lc_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, char const *fmt)
Convert a string to lowercase.
void fr_hmac_sha1(uint8_t digest[SHA1_DIGEST_LENGTH], uint8_t const *text, size_t text_len, uint8_t const *key, size_t key_len)
Calculate HMAC using SHA1.
size_t fr_pair_snprint(char *out, size_t outlen, VALUE_PAIR const *vp)
Print one attribute and value to a string.
static char randstr_salt[]
VALUE_PAIR * fr_cursor_remove(vp_cursor_t *cursor)
Remove the current pair.
void void fr_md5_final(uint8_t out[MD5_DIGEST_LENGTH], FR_MD5_CTX *ctx) CC_BOUNDED(__minbytes__
static ssize_t unescape_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, UNUSED REQUEST *request, char const *fmt)
Equivalent to the old safe_characters functionality in rlm_sql.
size_t strlcpy(char *dst, char const *src, size_t siz)
VALUE_PAIR * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute.
static char randstr_otp[]
void void MD5_DIGEST_LENGTH
char const * allowed_chars
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
String of printable characters.
static ssize_t expr_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
VALUE_PAIR * tmpl_cursor_next(vp_cursor_t *cursor, vp_tmpl_t const *vpt)
Returns the next VALUE_PAIR specified by vpt.
struct tm * localtime_r(time_t const *l_clock, struct tm *result)
static const CONF_PARSER module_config[]
struct expr_map_t expr_map_t
static bool get_operator(REQUEST *request, char const **string, expr_token_t *op)
A source or sink of value data.
static ssize_t next_time_xlat(char **out, size_t outlen, UNUSED void const *mod_inst, UNUSED void const *xlat_inst, REQUEST *request, char const *fmt)
Calculate number of seconds until the next n hour(s), day(s), week(s), year(s).
size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
Convert binary data to a hex string.
char const * cf_section_name2(CONF_SECTION const *cs)
#define USES_APPLE_DEPRECATED_API