23 RCSID(
"$Id: b0226b3e92eb81f737213b5d625de53596a52028 $")
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/parser.h>
27 #include <freeradius-devel/rad_assert.h>
31 #define PW_CAST_BASE (1850)
54 char *end = out + outlen - 1;
108 len =
strlcpy(out,
"true", outlen);
113 len =
strlcpy(out,
"false", outlen);
129 len =
strlcpy(p,
" && ", end - p);
133 len =
strlcpy(p,
" || ", end - p);
148 char const *p = start;
173 *out = talloc_array(ctx,
char, strlen(start) - 1);
174 if (!*out)
return -1;
190 if (quote ==
'/') quote =
'\0';
192 if (
value_data_from_str(ctx, &data, &src_type, NULL, start + 1, p - (start + 1), quote) < 0) {
193 *error =
"error parsing string";
198 *out = talloc_steal(ctx, data.ptr);
199 data.strvalue = NULL;
208 *error =
"End of string after escape";
212 if (p[1] == start[0]) {
221 *error =
"Unterminated string";
229 char const *p = start;
231 if ((*p ==
'"') || (*p ==
'\'') || (*p ==
'`') || (*p ==
'/')) {
244 *error =
"Unexpected escape";
258 if (isspace((
int) *p) || (*p ==
'&') || (*p ==
'|') ||
259 (*p ==
'!') || (*p ==
'=') || (*p ==
'<') || (*p ==
'>')) {
263 if ((*p ==
'"') || (*p ==
'\'') || (*p ==
'`')) {
264 *error =
"Unexpected start of string";
273 *error =
"Empty string is invalid";
277 *out = talloc_array(ctx,
char, len + 1);
278 memcpy(*out, start, len);
286 char const *p = start;
290 while (isspace((
int) *p)) p++;
292 if (*p !=
'<')
return 0;
296 while (*q && *q !=
'>') q++;
300 *error =
"Invalid data type in cast";
309 #ifdef WITH_ASCEND_BINARY
318 *error =
"Forbidden data type in cast";
327 *error =
"Cannot cast to this data type";
333 while (isspace((
int) *q)) q++;
364 c->
cast = c->
data.map->rhs->tmpl_da;
377 c->
cast = c->
data.map->rhs->tmpl_da;
386 c->
cast = c->
data.map->rhs->tmpl_da;
407 c->
cast = c->
data.map->rhs->tmpl_da;
413 c->
cast = c->
data.map->rhs->tmpl_da;
424 #define return_P(_x) *error = _x;goto return_p
425 #define return_0(_x) *error = _x;goto return_0
426 #define return_lhs(_x) *error = _x;goto return_lhs
427 #define return_rhs(_x) *error = _x;goto return_rhs
428 #define return_SLEN goto return_slen
445 fr_cond_t **pcond,
char const **error,
int flags)
448 char const *p = start;
449 char const *lhs_p, *rhs_p;
460 while (isspace((
int) *p)) p++;
463 return_P(
"Empty condition is invalid");
472 while (isspace((
int) *p)) p++;
478 return_P(
"Double negation is invalid");
497 if (!c->
data.child) {
498 return_P(
"Empty condition is invalid");
502 while (isspace((
int) *p)) p++;
516 return_P(
"Conditional check cannot begin with a regular expression");
536 (lhs[0] ==
'0') && (lhs[1] ==
'x') &&
537 ((slen & 0x01) == 0)) {
539 return_P(
"Empty octet string is invalid");
545 while (isspace((
int)*p)) p++;
566 return_P(
"No closing brace at end of string");
574 }
else if (((p[0] ==
'&') && (p[1] ==
'&')) ||
575 ((p[0] ==
'|') && (p[1] ==
'|'))) {
579 return_0(
"Cannot do cast for existence check");
614 return_P(
"Invalid text. Expected comparison operator");
622 }
else if (p[1] ==
'~') {
629 }
else if (p[1] ==
'*') {
631 return_P(
"Cannot use !* on a string");
638 goto invalid_operator;
648 }
else if (p[1] ==
'~') {
655 }
else if (p[1] ==
'*') {
657 return_P(
"Cannot use =* on a string");
693 while (isspace((
int) *p)) p++;
696 return_P(
"Expected text after operator");
715 if (c->
cast != cast_da) {
716 return_P(
"Cannot cast to a different data type");
737 return_P(
"Expected regular expression");
762 }
else if (!regex && (*p ==
'/')) {
763 return_P(
"Unexpected regular expression");
784 if (lhs) talloc_free(lhs);
785 if (rhs) talloc_free(rhs);
787 return -(lhs_p - start);
798 (rhs[0] ==
'0') && (rhs[1] ==
'x') &&
799 ((slen & 0x01) == 0)) {
801 return_P(
"Empty octet string is invalid");
815 map->
lhs->tmpl_da->flags.is_unknown &&
820 tlen =
tmpl_afrom_str(map, &map->
rhs, rhs, talloc_array_length(rhs) - 1, rhs_type,
842 c->
data.map->rhs->tmpl_iflag = iflag;
843 c->
data.map->rhs->tmpl_mflag = mflag;
858 return_0(
"Cannot use list references in condition");
879 return_0(
"Cannot use cast with regex comparison");
889 *error =
"Failed to parse field";
890 if (lhs) talloc_free(lhs);
891 if (rhs) talloc_free(rhs);
893 return -(lhs_p - start);
968 return_0(
"Cannot cast to attribute of incompatible size");
998 return_0(
"Attribute comparisons must be of the same data type");
1007 *error =
"Cannot use attribute reference on right side of condition";
1009 if (lhs) talloc_free(lhs);
1010 if (rhs) talloc_free(rhs);
1028 return_rhs(
"Must have string as value for attribute");
1042 *error =
"Value must be an unquoted string";
1044 if (lhs) talloc_free(lhs);
1045 if (rhs) talloc_free(rhs);
1047 return -(rhs_p - start);
1073 switch (c->
data.map->lhs->tmpl_da->
type) {
1075 if (strchr(c->
data.map->rhs->name,
'/') != NULL) {
1082 if (strchr(c->
data.map->rhs->name,
'/') != NULL) {
1096 ((da->
attr == PW_AUTH_TYPE) ||
1097 (da->
attr == PW_AUTZ_TYPE) ||
1098 (da->
attr == PW_ACCT_TYPE) ||
1099 (da->
attr == PW_SESSION_TYPE) ||
1100 (da->
attr == PW_POST_AUTH_TYPE) ||
1101 (da->
attr == PW_PRE_PROXY_TYPE) ||
1102 (da->
attr == PW_POST_PROXY_TYPE) ||
1103 (da->
attr == PW_PRE_ACCT_TYPE) ||
1104 (da->
attr == PW_RECV_COA_TYPE) ||
1105 (da->
attr == PW_SEND_COA_TYPE))) {
1113 return_rhs(
"Failed to parse value for attribute");
1126 c->
data.map->lhs->tmpl_da->attr,
1127 c->
data.map->rhs->tmpl_data_type);
1129 return_rhs(
"Cannot find type for attribute");
1131 c->
data.map->lhs->tmpl_da = da;
1168 bool may_be_attr =
true;
1176 for (i = 0; i < c->
data.map->lhs->len; i++) {
1178 may_be_attr =
false;
1182 if (c->
data.map->lhs->name[i] ==
'-') {
1185 may_be_attr =
false;
1191 if (!hyphens || (hyphens > 3)) may_be_attr =
false;
1197 if ((attr_slen > 0) && (vpt->
len == c->
data.map->lhs->len)) {
1198 talloc_free(c->
data.map->lhs);
1199 c->
data.map->lhs = vpt;
1209 while (isspace((
int) *p)) p++;
1218 return_P(
"Unexpected closing brace");
1222 while (isspace((
int) *p)) p++;
1231 return_P(
"No closing brace at end of string");
1237 if (!(((p[0] ==
'&') && (p[1] ==
'&')) ||
1238 ((p[0] ==
'|') && (p[1] ==
'|')))) {
1239 *error =
"Unexpected text after condition";
1241 if (lhs) talloc_free(lhs);
1242 if (rhs) talloc_free(rhs);
1244 return -(p - start);
1259 if (lhs) talloc_free(lhs);
1260 if (rhs) talloc_free(rhs);
1262 return slen - (p - start);
1287 child = talloc_steal(ctx, c->
data.child);
1288 c->
data.child = NULL;
1290 child->
next = talloc_steal(child, c->
next);
1320 child = talloc_steal(ctx, c->
data.child);
1321 c->
data.child = NULL;
1382 vpt = talloc_steal(c, c->
data.map->lhs);
1383 c->
data.map->lhs = NULL;
1392 TALLOC_FREE(c->
data.map);
1412 TALLOC_FREE(c->
data.map);
1442 DEBUG3(
"OPTIMIZING (%s %s %s) --> FALSE",
1443 c->
data.map->lhs->name,
1445 c->
data.map->rhs->name);
1452 TALLOC_FREE(c->
data.map);
1467 tmp = c->
data.map->rhs;
1468 c->
data.map->rhs = c->
data.map->lhs;
1469 c->
data.map->lhs = tmp;
1473 switch (c->
data.map->op) {
1495 return_0(
"Internal sanity check failed 1");
1545 if ((strcmp(c->
data.vpt->name,
"true") == 0) ||
1546 (strcmp(c->
data.vpt->name,
"1") == 0)) {
1548 TALLOC_FREE(c->
data.vpt);
1550 }
else if ((strcmp(c->
data.vpt->name,
"false") == 0) ||
1551 (strcmp(c->
data.vpt->name,
"0") == 0)) {
1553 TALLOC_FREE(c->
data.vpt);
1555 }
else if (!*c->
data.vpt->name) {
1557 TALLOC_FREE(c->
data.vpt);
1562 TALLOC_FREE(c->
data.vpt);
1569 for (q = c->
data.vpt->name;
1572 if (!isdigit((
int) *q)) {
1575 if (*q !=
'0') zeros =
false;
1588 TALLOC_FREE(c->
data.vpt);
1601 c->
data.vpt->name, 0);
1603 return_0(
"Expected a module return code");
1618 return_0(
"Internal sanity check failed 2");
1649 next = talloc_steal(ctx, c->
next);
1662 talloc_free(c->
next);
1674 next = talloc_steal(ctx, c->
next);
1687 talloc_free(c->
next);
1692 if (lhs) talloc_free(lhs);
1693 if (rhs) talloc_free(rhs);
1712 fr_cond_t **head,
char const **error,
int flags)
1726 if (!callback(ctx, c))
return false;
size_t map_snprint(char *out, size_t outlen, vp_map_t const *map)
Print a map to a string.
ssize_t tmpl_afrom_str(TALLOC_CTX *ctx, vp_tmpl_t **out, char const *name, size_t inlen, FR_TOKEN type, request_refs_t request_def, pair_lists_t list_def, bool do_escape)
Convert an arbitrary string into a vp_tmpl_t.
Ascend binary format a packed data structure.
vp_tmpl_t * lhs
Typically describes the attribute to add, modify or compare.
WiMAX IPv4 or IPv6 address depending on length.
const size_t dict_attr_sizes[PW_TYPE_MAX][2]
Map data types to min / max data sizes.
vp_tmpl_t * rhs
Typically describes a literal value or a src attribute to copy or compare.
Pre-parsed XLAT expansion.
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, vp_tmpl_t **out, 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.
static ssize_t condition_tokenize_string(TALLOC_CTX *ctx, char **out, char const **error, char const *start, FR_TOKEN *op)
const FR_NAME_NUMBER fr_tokens_table[]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
static ssize_t condition_tokenize_word(TALLOC_CTX *ctx, char const *start, char **out, FR_TOKEN *op, char const **error)
fr_dict_attr_t const * cast
Long extended attribute space attribute.
ssize_t fr_condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, fr_cond_t **head, char const **error, int flags)
Tokenize a conditional check.
size_t fr_cond_snprint(char *out, size_t outlen, fr_cond_t const *in)
const int fr_dict_attr_allowed_chars[256]
static bool condition_check_types(fr_cond_t *c, PW_TYPE lhs_type)
static ssize_t condition_tokenize_cast(char const *start, fr_dict_attr_t const **pda, char const **error)
Attribute not found in the global dictionary.
int fr_str2int(FR_NAME_NUMBER const *table, char const *name, int def)
int tmpl_define_unknown_attr(vp_tmpl_t *vpt)
Add an unknown fr_dict_attr_t specified by a vp_tmpl_t to the main dictionary.
const FR_NAME_NUMBER dict_attr_types[]
Map data types to names representing those types.
unsigned int attr
Attribute number.
Attributes in incoming or internally proxied request.
unsigned int vendor
Vendor that defines this attribute.
int radius_evaluate_map(REQUEST *request, int modreturn, int depth, fr_cond_t const *c)
bool fr_condition_walk(fr_cond_t *c, bool(*callback)(void *, fr_cond_t *), void *ctx)
Invalid (uninitialised) attribute type.
tmpl_type_t type
What type of value tmpl refers to.
char const * fr_strerror(void)
Get the last library error.
size_t len
Length of the raw string used to create the template.
#define RETURN_IF_TRUNCATED(_p, _ret, _max)
Boilerplate for checking truncation.
fr_dict_attr_t const * fr_dict_attr_by_type(fr_dict_t *dict, unsigned int vendor, unsigned int attr, PW_TYPE type)
Lookup a attribute by its its vendor and attribute numbers and data type.
Callout to an external script or program.
Vendor-Specific, for RADIUS attribute 26.
void bool map_cast_from_hex(vp_map_t *map, FR_TOKEN rhs_type, char const *rhs)
re-parse a map where the lhs is an unknown attribute.
static const FR_NAME_NUMBER allowed_return_codes[]
FR_TOKEN op
The operator that controls insertion of the dst attribute.
Extended attribute space attribute.
static ssize_t condition_tokenize(TALLOC_CTX *ctx, CONF_ITEM *ci, char const *start, bool brace, fr_cond_t **pcond, char const **error, int flags)
Tokenize a conditional check.
fr_cond_pass2_t pass2_fixup
size_t tmpl_snprint(char *buffer, size_t bufsize, vp_tmpl_t const *vpt, fr_dict_attr_t const *values)
Print a vp_tmpl_t to a string.
int value_data_from_str(TALLOC_CTX *ctx, value_data_t *dst, PW_TYPE *src_type, fr_dict_attr_t const *src_enumv, char const *src, ssize_t src_len, char quote)
Convert string value to a value_data_t type.
size_t strlcpy(char *dst, char const *src, size_t siz)
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
fr_dict_attr_t const * fr_dict_attr_by_num(fr_dict_t *dict, unsigned int vendor, unsigned int attr)
Lookup a fr_dict_attr_t by its vendor and attribute numbers.
String of printable characters.
Contains nested attributes.
int fr_substr2int(FR_NAME_NUMBER const *table, char const *name, int def, int len)
int tmpl_cast_in_place(vp_tmpl_t *vpt, PW_TYPE type, fr_dict_attr_t const *enumv)
Convert vp_tmpl_t of type TMPL_TYPE_UNPARSED or TMPL_TYPE_DATA to TMPL_TYPE_DATA of type specified...
A source or sink of value data.
PW_TYPE
Internal data types used within libfreeradius.
Extended attribute, vendor specific.