25 #include <freeradius-devel/ldap/base.h>
39 #define FILTER_ATTR_MAX_LEN 256
40 #define FILTER_VALUE_MAX_LEN 256
89 if (ret < 0)
return ret;
103 if (ret < 0)
return ret;
132 fr_sbuff_marker(&marker, sbuff);
144 MEM(node->attr = talloc_zero_array(node,
char, len+1));
145 memcpy(node->attr, attr_buffer, len);
219 fr_sbuff_set_to_start(&val_sbuff);
245 val_buffer, len, NULL,
false) < 0) {
290 static bool const logical_op_chars[
UINT8_MAX +1] = {
291 [
'!'] =
true, [
'&'] =
true, [
'|'] =
true,
303 fr_sbuff_marker(&marker, sbuff);
311 if (ret < 0)
return ret;
380 bool filter_state =
false;
407 DEBUG3(
"%*sLDAP filter group %s results in %s",
depth,
"", group->
orig, (filter_state ?
"TRUE" :
"FALSE"));
411 #define DEBUG_LDAP_ATTR_VAL if (DEBUG_ENABLED3) { \
412 fr_value_box_t value_box; \
413 fr_ldap_berval_to_value_str_shallow(&value_box, values[i]); \
414 DEBUG3("%*s Evaluating attribute \"%s\", value \"%pV\"", depth, "", node->attr, &value_box); \
427 struct berval **values;
429 bool filter_state =
false;
437 values = ldap_get_values_len(conn->
handle,
msg, node->attr);
438 count = ldap_count_values_len(values);
442 filter_state = (
count > 0 ?
true :
false);
446 for (i = 0; i <
count; i++) {
448 if ((node->value->vb_length == values[i]->bv_len) &&
449 (
strncasecmp(values[i]->bv_val, node->value->vb_strvalue, values[i]->bv_len) == 0)) {
462 char const *v, *t, *v_end, *t_end;
469 t_end = node->value->vb_strvalue + node->value->vb_length - 1;
471 for (i = 0; i <
count; i++) {
473 t = node->value->vb_strvalue;
474 v = values[i]->bv_val;
475 v_end = values[i]->bv_val + values[i]->bv_len - 1;
482 while ((v <= v_end) && (t <= t_end)) {
494 while ((tolower((
uint8_t) *t) != tolower((
uint8_t) *v)) && (v <= v_end)) v++;
507 if (((v > v_end) && (t > t_end)) || ((t >= t_end) && (*t_end ==
'*'))) {
525 for (i = 0; i <
count; i++) {
530 if (values[i]->bv_len > 10)
continue;
536 memcpy(
buffer, values[i]->bv_val, values[i]->bv_len);
537 buffer[values[i]->bv_len] =
'\0';
542 if (
value >= node->value->vb_uint32) filter_state =
true;
548 if (
value & node->value->vb_uint32) filter_state =
true;
551 if (
value | node->value->vb_uint32) filter_state =
true;
557 if (filter_state)
break;
568 ldap_value_free_len(values);
571 DEBUG3(
"%*sLDAP filter returns %s",
depth,
"", (filter_state ?
"TRUE" :
"FALSE"));
static int const char char buffer[256]
#define L(_str)
Helper for initialising arrays of string literals.
fr_dcursor_eval_t void const * uctx
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
static int fr_dlist_insert_head(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the head of a list.
Head of a doubly linked list.
fr_slen_t fr_ldap_filter_parse(TALLOC_CTX *ctx, fr_dlist_head_t **root, fr_sbuff_t *filter, filter_attr_check_t attr_check, void *uctx)
Parse an LDAP filter into its component nodes.
static fr_slen_t ldap_filter_parse_filter(ldap_filter_t *node, fr_sbuff_t *sbuff, int depth, filter_attr_check_t attr_check, void *uctx)
Parse individual LDAP filter.
static size_t ldap_filter_op_table_len
bool fr_ldap_filter_eval(fr_dlist_head_t *root, fr_ldap_connection_t *conn, LDAPMessage *msg)
Evaluate an LDAP filter.
static bool const fr_ldap_attr_allowed_chars[UINT8_MAX+1]
static bool ldap_filter_group_eval(ldap_filter_t *group, fr_ldap_connection_t *conn, LDAPMessage *msg, int depth)
Evaluate a group of LDAP filters.
#define FILTER_VALUE_MAX_LEN
#define DEBUG_LDAP_ATTR_VAL
#define FILTER_ATTR_MAX_LEN
static fr_slen_t ldap_filter_parse_node(ldap_filter_t *node, fr_sbuff_t *sbuff, int depth, filter_attr_check_t attr_check, void *uctx)
Parse individual LDAP filter nodes.
static fr_table_num_sorted_t const ldap_filter_op_table[]
static bool ldap_filter_node_eval(ldap_filter_t *node, fr_ldap_connection_t *conn, LDAPMessage *msg, int depth)
Evaluate a single LDAP filter node.
static fr_slen_t ldap_filter_parse_logic(ldap_filter_t *node, fr_sbuff_t *sbuff, int depth, filter_attr_check_t attr_check, void *uctx)
Parse LDAP filter logic group.
LDAP * handle
libldap handle.
#define LDAP_MATCHING_RULE_BIT_OR
OID of bit-wise OR LDAP match rule.
@ LDAP_FILTER_GROUP
The filter node is a parent of a group which will be combined using a logical operator.
@ LDAP_FILTER_NODE
The filter node is an individual one to be evaluated against an attribute.
ldap_filter_op_t
Operators for use in LDAP filters.
@ LDAP_FILTER_OP_BIT_AND
Bitwise AND comparison.
@ LDAP_FILTER_OP_PRESENT
Attribute present.
@ LDAP_FILTER_OP_SUBSTR
Attribute matches string with wildcards.
@ LDAP_FILTER_OP_EQ
Attribute equals value.
@ LDAP_FILTER_OP_LE
Attribute less than or equal to value.
@ LDAP_FILTER_OP_BIT_OR
Bitwise OR comparison.
@ LDAP_FILTER_OP_GE
Attribute greater than or equal to value.
@ LDAP_FILTER_OP_UNSET
Attribute not set yet.
char * orig
Text representation of filter for debug messages,.
ldap_filter_type_t filter_type
Type of this filter node.
#define LDAP_MATCHING_RULE_BIT_AND
OID of bit-wise AND LDAP match rule.
int(* filter_attr_check_t)(char const *attr, void *uctx)
Tracks the state of a libldap connection handle.
Structure to hold parsed details of LDAP filters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
size_t fr_sbuff_out_bstrncpy_until(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, fr_sbuff_term_t const *tt, fr_sbuff_unescape_rules_t const *u_rules)
size_t fr_sbuff_out_bstrncpy_allowed(fr_sbuff_t *out, fr_sbuff_t *in, size_t len, bool const allowed[static UINT8_MAX+1])
static uint8_t depth(fr_minmax_heap_index_t i)
int strncasecmp(char *s1, char *s2, int n)
static int attr_check(CONF_SECTION *conf, tmpl_t *tmpl, char const *name, fr_dict_attr_flags_t *flags)
size_t fr_sbuff_adv_past_allowed(fr_sbuff_t *sbuff, size_t len, bool const allowed[static UINT8_MAX+1], fr_sbuff_term_t const *tt)
Wind position past characters in the allowed set.
char * fr_sbuff_adv_to_chr(fr_sbuff_t *sbuff, size_t len, char c)
Wind position to first instance of specified char.
bool fr_sbuff_next_if_char(fr_sbuff_t *sbuff, char c)
Return true if the current char matches, and if it does, advance.
#define fr_sbuff_out_by_longest_prefix(_match_len, _out, _table, _sbuff, _def)
#define fr_sbuff_adv_past_str_literal(_sbuff, _needle)
#define fr_sbuff_set(_dst, _src)
#define fr_sbuff_diff(_a, _b)
#define FR_SBUFF_IN(_start, _len_or_end)
#define fr_sbuff_current(_sbuff_or_marker)
#define fr_sbuff_extend(_sbuff_or_marker)
#define SBUFF_CHAR_CLASS_ALPHA_NUM
#define fr_sbuff_is_char(_sbuff_or_marker, _c)
#define FR_SBUFF_ERROR_RETURN(_sbuff_or_marker)
#define fr_sbuff_advance(_sbuff_or_marker, _len)
#define fr_sbuff_switch(_sbuff_or_marker, _eob)
#define FR_SBUFF_TERM(_str)
Initialise a terminal structure with a single string.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
An element in a lexicographically sorted array of name to num mappings.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
#define fr_strerror_const(_msg)
ssize_t fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, char const *in, size_t inlen, fr_sbuff_unescape_rules_t const *erules, bool tainted)
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.