void pairreplace(VALUE_PAIR **first, VALUE_PAIR *add);
int paircmp(VALUE_PAIR *check, VALUE_PAIR *data);
VALUE_PAIR *paircopyvp(const VALUE_PAIR *vp);
+VALUE_PAIR *paircopyvpdata(const DICT_ATTR *da, const VALUE_PAIR *vp);
VALUE_PAIR *paircopy(VALUE_PAIR *vp);
VALUE_PAIR *paircopy2(VALUE_PAIR *vp, unsigned int attr, unsigned int vendor, int8_t tag);
void pairmove(VALUE_PAIR **to, VALUE_PAIR **from);
/* for paircompare_register */
typedef int (*RAD_COMPARE_FUNC)(void *instance, REQUEST *,VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR *, VALUE_PAIR **);
-typedef enum request_fail_t {
- REQUEST_FAIL_UNKNOWN = 0,
- REQUEST_FAIL_NO_THREADS, /* no threads to handle it */
- REQUEST_FAIL_DECODE, /* rad_decode didn't like it */
- REQUEST_FAIL_PROXY, /* call to proxy modules failed */
- REQUEST_FAIL_PROXY_SEND, /* proxy_send didn't like it */
- REQUEST_FAIL_NO_RESPONSE, /* we weren't told to respond, so we reject */
- REQUEST_FAIL_HOME_SERVER, /* the home server didn't respond */
- REQUEST_FAIL_HOME_SERVER2, /* another case of the above */
- REQUEST_FAIL_HOME_SERVER3, /* another case of the above */
- REQUEST_FAIL_NORMAL_REJECT, /* authentication failure */
- REQUEST_FAIL_SERVER_TIMEOUT /* the server took too long to process the request */
+typedef enum request_fail {
+ REQUEST_FAIL_UNKNOWN = 0,
+ REQUEST_FAIL_NO_THREADS, //!< No threads to handle it.
+ REQUEST_FAIL_DECODE, //!< Rad_decode didn't like it.
+ REQUEST_FAIL_PROXY, //!< Call to proxy modules failed.
+ REQUEST_FAIL_PROXY_SEND, //!< Proxy_send didn't like it.
+ REQUEST_FAIL_NO_RESPONSE, //!< We weren't told to respond,
+ //!< so we reject.
+ REQUEST_FAIL_HOME_SERVER, //!< The home server didn't respond.
+ REQUEST_FAIL_HOME_SERVER2, //!< Another case of the above.
+ REQUEST_FAIL_HOME_SERVER3, //!< Another case of the above.
+ REQUEST_FAIL_NORMAL_REJECT, //!< Authentication failure.
+ REQUEST_FAIL_SERVER_TIMEOUT //!< The server took too long to
+ //!< process the request.
} request_fail_t;
/*
int radius_request(REQUEST **request, request_refs_t name);
request_refs_t radius_request_name(const char **name, request_refs_t unknown);
+
+typedef enum vpt_type {
+ VPT_TYPE_UNKNOWN = 0,
+ VPT_TYPE_LITERAL, //!< Is a literal string.
+ VPT_TYPE_XLAT, //!< Needs to be expanded.
+ VPT_TYPE_ATTR, //!< Is an attribute.
+ VPT_TYPE_LIST, //!< Is a list.
+ VPT_TYPE_EXEC //!< Needs to be executed.
+} vpt_type_t;
+
+extern const FR_NAME_NUMBER vpt_types[];
+
/** A pre-parsed template attribute
*
* Value pair template, used when processing various mappings sections
pair_lists_t list; //!< List to search or insert in.
const DICT_ATTR *da; //!< Resolved dictionary attribute.
- int do_xlat; //!< Controls whether the VP value
- //!< (when it's created), is also
- //!< xlat expanded.
+ vpt_type_t type; //!< What type of value tmpl refers to.
} value_pair_tmpl_t;
/** Value pair map
FR_TOKEN op; //!< The operator that controls
//!< insertion of the dst attribute.
+ CONF_ITEM *ci; //!< Config item that the map was
+ //!< created from. Mainly used for
+ //!< logging validation errors.
+
struct value_pair_map *next; //!< The next valuepair map.
} value_pair_map_t;
return n;
}
+/** Copy data from one VP to another
+ *
+ * Allocate a new pair using da, and copy over the value from the specified
+ * vp.
+ *
+ * @todo Should be able to do type conversions.
+ *
+ * @param[in] da of new attribute to alloc.
+ * @param[in] vp to copy data from.
+ * @return the new valuepair.
+ */
+VALUE_PAIR *paircopyvpdata(const DICT_ATTR *da, const VALUE_PAIR *vp)
+{
+ VALUE_PAIR *n;
+
+ if (!vp) return NULL;
+
+ if (da->type != vp->type) return NULL;
+
+ n = pairalloc(da);
+ if (!n) {
+ return NULL;
+ }
+
+ memcpy(&(n->data), &(vp->data), sizeof(n->data));
+
+ n->length = vp->length;
+
+ if ((n->type == PW_TYPE_TLV) &&
+ (n->vp_tlv != NULL)) {
+ n->vp_tlv = malloc(n->length);
+ memcpy(n->vp_tlv, vp->vp_tlv, n->length);
+ }
+
+ return n;
+}
+
/** Copy matching pairs
*
{ NULL , -1 }
};
+const FR_NAME_NUMBER vpt_types[] = {
+ {"unknown", VPT_TYPE_UNKNOWN },
+ {"literal", VPT_TYPE_LITERAL },
+ {"expanded", VPT_TYPE_XLAT },
+ {"attribute ref", VPT_TYPE_ATTR },
+ {"list", VPT_TYPE_LIST },
+ {"exec", VPT_TYPE_EXEC }
+};
+
struct cmp {
unsigned int attribute;
unsigned int otherattr;
* No colon was found and the first char was upper case
* indicating an attribute.
*
- * This allows the function to be used to resolve list names too.
*/
q = strchr(p, ':');
if (((q && (q[1] >= '0') && (q[1] <= '9'))) ||
return -1;
}
+ if (*p == '\0') {
+ vpt->type = VPT_TYPE_LIST;
+
+ return 0;
+ }
+
vpt->da = dict_attrbyname(p);
if (!vpt->da) {
radlog(L_ERR, "Attribute \"%s\" unknown", p);
-
+
return -1;
}
+ vpt->type = VPT_TYPE_ATTR;
+
return 0;
}
{
case T_BARE_WORD:
case T_SINGLE_QUOTED_STRING:
- vpt->do_xlat = FALSE;
- break;
- case T_BACK_QUOTED_STRING:
+ vpt->type = VPT_TYPE_LITERAL;
+ break;
case T_DOUBLE_QUOTED_STRING:
- vpt->do_xlat = TRUE;
- break;
+ vpt->type = VPT_TYPE_XLAT;
+ break;
+ case T_BACK_QUOTED_STRING:
+ vpt->type = VPT_TYPE_EXEC;
+ break;
default:
rad_assert(0);
return NULL;
const char *attr;
const char *value;
FR_TOKEN type;
+ CONF_ITEM *ci = cf_pairtoitem(cp);
+
+ if (!cp) return NULL;
map = rad_calloc(sizeof(value_pair_map_t));
attr = cf_pair_attr(cp);
value = cf_pair_value(cp);
if (!value) {
- cf_log_err(cf_pairtoitem(cp), "Missing attribute value");
+ cf_log_err(ci, "Missing attribute value");
goto error;
}
}
map->op = cf_pair_operator(cp);
+ map->ci = ci;
+
+ /*
+ * Lots of sanity checks for insane people...
+ */
+
+ /*
+ * We don't support implicit type conversion
+ */
+ if (map->dst->da && map->src->da &&
+ (map->src->da->type != map->dst->da->type)) {
+ cf_log_err(ci, "Attribute type mismatch");
+
+ goto error;
+ }
+
+ /*
+ * What exactly where you expecting to happen here?
+ */
+ if ((map->dst->type == VPT_TYPE_ATTR) &&
+ (map->src->type == VPT_TYPE_LIST)) {
+ cf_log_err(ci, "Can't copy list into an attribute");
+
+ goto error;
+ }
+
+ switch (map->src->type)
+ {
+
+ /*
+ * Only += and -= operators are supported for list copy.
+ */
+ case VPT_TYPE_LIST:
+ switch (map->op) {
+ case T_OP_SUB:
+ case T_OP_ADD:
+ break;
+
+ default:
+ cf_log_err(ci, "Operator \"%s\" not allowed "
+ "for list copy",
+ fr_int2str(fr_tokens, map->op,
+ "¿unknown?"));
+ goto error;
+ }
+ break;
+ /*
+ * @todo add support for exec expansion.
+ */
+ case VPT_TYPE_EXEC:
+ cf_log_err(ci, "Exec values are not allowed");
+ break;
+ default:
+ break;
+ }
return map;
*
* Uses 'name2' of section to set default request and lists.
*
- * @param[in] cs to convert to map.
+ * @param[in] parent to convert to map.
* @param[out] head Where to store the head of the map.
* @param[in] dst_list_def The default destination list, usually dictated by
* the section the module is being called in.
* @param[in] max number of mappings to process.
* @return -1 on error, else 0.
*/
-int radius_attrmap(CONF_SECTION *cs, value_pair_map_t **head,
+int radius_attrmap(CONF_SECTION *parent, value_pair_map_t **head,
pair_lists_t dst_list_def, pair_lists_t src_list_def,
unsigned int max)
{
request_refs_t request_def = REQUEST_CURRENT;
+ CONF_SECTION *cs;
CONF_ITEM *ci = cf_sectiontoitem(cs);
CONF_PAIR *cp;
*head = NULL;
tail = head;
+ if (!parent) return 0;
+
+ cs = cf_section_sub_find(parent, "update");
if (!cs) return 0;
cs_list = p = cf_section_name2(cs);
/** Convert value_pair_map_t to VALUE_PAIR(s) and add them to a REQUEST.
*
* Takes a single value_pair_map_t, resolves request and list identifiers
- * to pointers in the current request, the attempts to retrieve module
+ * to pointers in the current request, then attempts to retrieve module
* specific value(s) using callback, and adds the resulting values to the
* correct request/list.
*
return 0;
}
+ switch (vpt.type)
+ {
/*
* May not may not be found, but it *is* a known name.
*/
- *vp_p = pairfind(*vps, vpt.da->attr, vpt.da->vendor, TAG_ANY);
-
+ case VPT_TYPE_ATTR:
+ *vp_p = pairfind(*vps, vpt.da->attr, vpt.da->vendor, TAG_ANY);
+ break;
+
+ case VPT_TYPE_LIST:
+ *vp_p = *vps;
+ break;
+
+ default:
+ rad_assert(0);
+ return -1;
+ break;
+ }
+
return 0;
}
if (c->request && request->packet) {
RDEBUG2("Merging cached request list:");
- rdebug_pair_list(2, request, c->control);
+ rdebug_pair_list(2, request, c->request);
vp = paircopy(c->request);
pairmove(&request->packet->vps, &vp);
if (c->reply && request->reply) {
RDEBUG2("Merging cached reply list:");
- rdebug_pair_list(2, request, c->control);
+ rdebug_pair_list(2, request, c->reply);
vp = paircopy(c->reply);
pairmove(&request->reply->vps, &vp);
for (map = inst->maps; map != NULL; map = map->next)
{
rad_assert(map->dst && map->src);
- rad_assert(map->dst->da);
/*
* Specifying inner/outer request doesn't work here
/*
* Resolve the destination in the current request.
- * We need to add the to_cache there too if any of these are
+ * We need to add the to_cache there too if any of these
+ * are.
* true :
* - Map specifies an xlat'd string.
* - Map specifies a literal string.
* - Map src and dst lists differ.
+ * - Map src and dst attributes differ
*/
- from = NULL;
- if (!map->src->da || (map->src->list != map->dst->list))
+ to_req = NULL;
+ if (!map->src->da || (map->src->list != map->dst->list) ||
+ (map->src->da != map->dst->da))
{
context = request;
/*
* We infer that src was an attribute ref from the fact
* it contains a da.
*/
- da = map->src->da;
- if (da) {
+ RDEBUG4(":: dst is \"%s\" src is \"%s\"",
+ fr_int2str(vpt_types, map->dst->type, "¿unknown?"),
+ fr_int2str(vpt_types, map->src->type, "¿unknown?"));
+
+ switch (map->src->type)
+ {
+ case VPT_TYPE_ATTR:
+ from = NULL;
+ da = map->src->da;
context = request;
if (radius_request(&context, map->src->request) == 0) {
from = radius_list(context, map->src->list);
}
/*
- * Can't add this attribute if the list isn't
+ * Can't add the attribute if the list isn't
* valid.
*/
if (!from) continue;
case T_OP_SET:
case T_OP_EQ:
case T_OP_SUB:
- vp = paircopyvp(found);
- vp->operator = map->op;
+ vp = map->dst->type == VPT_TYPE_LIST ?
+ paircopyvp(found) :
+ paircopyvpdata(map->dst->da, found);
+
+ if (!vp) continue;
+
pairadd(to_cache, vp);
+
+ if (to_req) {
+ vp = paircopyvp(vp);
+ radius_pairmove(request, to_req, vp);
+ }
break;
case T_OP_ADD:
do {
- vp = paircopyvp(found);
+ vp = map->dst->type == VPT_TYPE_LIST ?
+ paircopyvp(found) :
+ paircopyvpdata(map->dst->da,
+ found);
+ if (!vp) continue;
+
vp->operator = map->op;
pairadd(to_cache, vp);
rad_assert(0);
return NULL;
}
+ break;
+ case VPT_TYPE_LIST:
+ rad_assert(map->src->type == VPT_TYPE_LIST);
+
+ from = NULL;
+ context = request;
+ if (radius_request(&context, map->src->request) == 0) {
+ from = radius_list(context, map->src->list);
+ }
+ if (!from) continue;
+
+ found = paircopy(*from);
+ if (!found) continue;
+
+ for (vp = found; vp != NULL; vp = vp->next) {
+ RDEBUG("\t%s%s %s %s%s", map->dst->name,
+ vp->name,
+ fr_int2str(fr_tokens, map->op, "¿unknown?"),
+ map->src->name,
+ vp->name);
+ vp->operator = map->op;
+ }
+
+ pairadd(to_cache, found);
+
+ if (to_req) {
+ vp = paircopy(found);
+ radius_pairmove(request, to_req, vp);
+ }
+
+ break;
/*
* It was most likely a double quoted string that now
* needs to be expanded.
*/
- } else if (map->src->do_xlat) {
+ case VPT_TYPE_XLAT:
if (radius_xlat(buffer, sizeof(buffer), map->src->name,
request, NULL, NULL) <= 0) {
continue;
/*
* Literal string.
*/
- } else {
+ case VPT_TYPE_LITERAL:
RDEBUG("\t%s %s '%s'", map->dst->name,
fr_int2str(fr_tokens, map->op, "¿unknown?"),
map->src->name);
}
break;
+
+ default:
+ rad_assert(0);
+ return NULL;
}
}
*/
static int cache_verify(rlm_cache_t *inst, value_pair_map_t **head)
{
- CONF_ITEM *ci;
- CONF_PAIR *cp;
- FR_TOKEN op;
- FR_TOKEN type;
-
- for (ci = cf_item_find_next(inst->cs, NULL);
- ci != NULL;
- ci = cf_item_find_next(inst->cs, ci)) {
- cp = cf_itemtopair(ci);
- type = cf_pair_value_type(cp);
- op = cf_pair_operator(cp);
-
- switch (type) {
- case T_BARE_WORD:
- switch (op) {
+ value_pair_map_t *map;
+
+ if (radius_attrmap(inst->cs, head, PAIR_LIST_REQUEST,
+ PAIR_LIST_REQUEST, MAX_ATTRMAP) < 0) {
+ return -1;
+ }
+
+ if (!*head) {
+ cf_log_err(cf_sectiontoitem(inst->cs),
+ "Cache config must contain an update section, and "
+ "that section must not be empty");
+
+ return -1;
+ }
+
+ for (map = *head; map != NULL; map = map->next) {
+
+ if ((map->dst->type != VPT_TYPE_ATTR) &&
+ (map->dst->type != VPT_TYPE_LIST)) {
+ cf_log_err(map->ci, "Left operand must be an attribute "
+ "ref or a list");
+
+ return -1;
+ }
+
+ switch (map->src->type)
+ {
+ /*
+ * Only =, :=, += and -= operators are supported for
+ * cache entries.
+ */
+ case VPT_TYPE_LITERAL:
+ case VPT_TYPE_XLAT:
+ case VPT_TYPE_ATTR:
+ switch (map->op) {
case T_OP_SET:
case T_OP_EQ:
case T_OP_SUB:
case T_OP_ADD:
break;
-
+
default:
- cf_log_err(ci, "Operator \"%s\" not "
- "allowed for attribute references",
- fr_int2str(fr_tokens, op,
- "¿unknown?"));
+ cf_log_err(map->ci, "Operator \"%s\" not "
+ "allowed for %s values",
+ fr_int2str(fr_tokens, map->op,
+ "¿unknown?"),
+ fr_int2str(vpt_types, map->src->type,
+ "¿unknown?"));
return -1;
}
-
- break;
- case T_SINGLE_QUOTED_STRING:
- case T_DOUBLE_QUOTED_STRING:
- break;
-
default:
- cf_log_err(ci, "Unsupported value type \"%s\"",
- fr_int2str(fr_tokens, type, "¿unknown?"));
- return -1;
+ break;
}
}
-
- /*
- * We end up iterating over the entire section twice, but this
- * is only done on instantiate so it's not really that much of an
- * issue.
- */
- return radius_attrmap(inst->cs, head, PAIR_LIST_REQUEST,
- PAIR_LIST_REQUEST, MAX_ATTRMAP);
+ return 0;
}
/*
radius_xlat(buffer, sizeof(buffer), inst->key, request, NULL, NULL);
+ list = radius_list_name(&p, PAIR_LIST_REQUEST);
+
+ target = dict_attrbyname(p);
+ if (!target) {
+ radlog(L_ERR, "rlm_cache: Unknown attribute \"%s\"", p);
+ return -1;
+ }
+
PTHREAD_MUTEX_LOCK(&inst->cache_mutex);
c = cache_find(inst, request, buffer);
RDEBUG("No cache entry for key \"%s\"", buffer);
goto done;
}
-
- list = radius_list_name(&p, PAIR_LIST_REQUEST);
+
switch (list) {
case PAIR_LIST_REQUEST:
vps = c->request;
fr_int2str(pair_lists, list, "¿Unknown?"));
return 0;
}
-
- target = dict_attrbyname(p);
- if (!target) {
- radlog(L_ERR, "rlm_cache: Unknown attribute \"%s\"", p);
- goto done;
- }
-
+
vp = pairfind(vps, target->attr, target->vendor, TAG_ANY);
if (!vp) {
RDEBUG("No instance of this attribute has been cached");
const char *xlat_name;
rlm_cache_t *inst;
- inst = rad_malloc(sizeof(*inst));
- if (!inst) {
- return -1;
- }
- memset(inst, 0, sizeof(*inst));
-
+ inst = rad_calloc(sizeof(*inst));
+ inst->cs = conf;
/*
* If the configuration parameters can't be parsed, then
* fail.
cache_detach(inst);
return -1;
}
-
-
- inst->cs = cf_section_sub_find(conf, "update");
- if (!inst->cs) {
- radlog(L_ERR, "rlm_cache: Failed to find \"update\" subsection");
- cache_detach(inst);
- return -1;
- }
/*
* Make sure the users don't screw up too badly.
return 0;
}
+static int ldap_map_verify(ldap_instance *inst, value_pair_map_t **head)
+{
+ value_pair_map_t *map;
+
+ if (radius_attrmap(inst->cs, head, PAIR_LIST_REPLY,
+ PAIR_LIST_REQUEST, MAX_ATTRMAP) < 0) {
+ return -1;
+ }
+ /*
+ * Attrmap only performs some basic validation checks, we need
+ * to do rlm_cache specific checks here.
+ */
+ for (map = *head; map != NULL; map = map->next) {
+ if (map->dst->type != VPT_TYPE_ATTR) {
+ cf_log_err(map->ci, "Left operand must be an "
+ "attribute ref");
+
+ return -1;
+ }
+
+ if (map->src->type == VPT_TYPE_LIST) {
+ cf_log_err(map->ci, "Right operand must not be "
+ "a list");
+
+ return -1;
+ }
+
+ switch (map->src->type)
+ {
+ /*
+ * Only =, :=, += and -= operators are supported for
+ * cache entries.
+ */
+ case VPT_TYPE_LITERAL:
+ case VPT_TYPE_XLAT:
+ case VPT_TYPE_ATTR:
+ switch (map->op) {
+ case T_OP_SET:
+ case T_OP_EQ:
+ case T_OP_SUB:
+ case T_OP_ADD:
+ break;
+
+ default:
+ cf_log_err(map->ci, "Operator \"%s\" not "
+ "allowed for %s values",
+ fr_int2str(fr_tokens, map->op,
+ "¿unknown?"),
+ fr_int2str(vpt_types, map->src->type,
+ "¿unknown?"));
+ return -1;
+ }
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
/** Parses config
* Uses section of radiusd config file passed as parameter to create an
* instance of the module.
static int ldap_instantiate(CONF_SECTION * conf, void **instance)
{
ldap_instance *inst;
- CONF_SECTION *cs;
inst = rad_calloc(sizeof *inst);
inst->cs = conf;
/*
* Build the attribute map
*/
- cs = cf_section_sub_find(conf, "update");
- if (cs) {
- if (radius_attrmap(cs, &(inst->user_map), PAIR_LIST_REPLY,
- PAIR_LIST_REQUEST, MAX_ATTRMAP) < 0) {
- goto error;
- }
+ if (ldap_map_verify(inst, &(inst->user_map)) < 0) {
+ goto error;
}
/*
name = expanded->attrs[total++];
if (!name) return;
- if (map->src->do_xlat) {
+ switch (map->src->type)
+ {
+ case VPT_TYPE_XLAT:
+ case VPT_TYPE_ATTR:
rad_cfree(name);
+ break;
+ default:
+ break;
}
}
}
size_t len;
char *buffer;
+ VALUE_PAIR *found, **from = NULL;
+ REQUEST *context;
+
for (map = maps; map != NULL; map = map->next)
{
- if (map->src->do_xlat) {
+ switch (map->src->type)
+ {
+ case VPT_TYPE_XLAT:
buffer = rad_malloc(MAX_ATTR_STR_LEN);
len = radius_xlat(buffer, MAX_ATTR_STR_LEN,
map->src->name, request, NULL, NULL);
- if (!len) {
+ if (len <= 0) {
RDEBUG("Expansion of LDAP attribute "
"\"%s\" failed", map->src->name);
- expanded->attrs[total] = NULL;
-
- xlat_attrsfree(expanded);
-
- return -1;
+ goto error;
}
expanded->attrs[total++] = buffer;
- } else {
+ break;
+
+ case VPT_TYPE_ATTR:
+ context = request;
+
+ if (radius_request(&context, map->src->request) == 0) {
+ from = radius_list(context, map->src->list);
+ }
+ if (!from) continue;
+
+ found = pairfind(*from, map->src->da->attr,
+ map->src->da->vendor, TAG_ANY);
+ if (!found) continue;
+
+ buffer = rad_malloc(MAX_ATTR_STR_LEN);
+ strlcpy(buffer, found->vp_strvalue, MAX_ATTR_STR_LEN);
+
+ expanded->attrs[total++] = buffer;
+ break;
+
+ case VPT_TYPE_LITERAL:
expanded->attrs[total++] = map->src->name;
+ break;
+ default:
+ rad_assert(0);
+ error:
+ expanded->attrs[total] = NULL;
+
+ xlat_attrsfree(expanded);
+
+ return -1;
}
+
}
expanded->attrs[total] = NULL;
*/
if (inst->expect_password && (debug_flag > 1)) {
if (!pairfind(request->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY) &&
- !pairfind(request->config_items, PW_NT_PASSWORD, 0, TAG_ANY) &&
- !pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) &&
- !pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0, TAG_ANY) &&
- !pairfind(request->config_items, PW_CRYPT_PASSWORD, 0, TAG_ANY)) {
- RDEBUG("WARNING: No \"known good\" password "
- "was found in LDAP. Are you sure that "
- "the user is configured correctly?");
- }
+ !pairfind(request->config_items, PW_NT_PASSWORD, 0, TAG_ANY) &&
+ !pairfind(request->config_items, PW_USER_PASSWORD, 0, TAG_ANY) &&
+ !pairfind(request->config_items, PW_PASSWORD_WITH_HEADER, 0, TAG_ANY) &&
+ !pairfind(request->config_items, PW_CRYPT_PASSWORD, 0, TAG_ANY)) {
+ RDEBUG("WARNING: No \"known good\" password "
+ "was found in LDAP. Are you sure that "
+ "the user is configured correctly?");
+ }
}
}
passed[last_pass] = NULL;
} else if (do_xlat) {
p = rad_malloc(1024);
- radius_xlat(p, 1024, value, request, NULL, NULL);
-
- if (*p == '\0') {
-
+ if (radius_xlat(p, 1024, value, request, NULL, NULL) <= 0) {
RDEBUG("xlat failed or empty value string, "
"skipping attribute \"%s\"", attr);
switch (op)
{
- /*
- * T_OP_EQ is *NOT* supported, it is impossible to
- * support because of the lack of transactions in LDAP
- */
- case T_OP_ADD:
- mod_s[total].mod_op = LDAP_MOD_ADD;
+ /*
+ * T_OP_EQ is *NOT* supported, it is impossible to
+ * support because of the lack of transactions in LDAP
+ */
+ case T_OP_ADD:
+ mod_s[total].mod_op = LDAP_MOD_ADD;
break;
- case T_OP_SET:
- mod_s[total].mod_op = LDAP_MOD_REPLACE;
+
+ case T_OP_SET:
+ mod_s[total].mod_op = LDAP_MOD_REPLACE;
break;
- case T_OP_SUB:
- case T_OP_CMP_FALSE:
- mod_s[total].mod_op = LDAP_MOD_DELETE;
+
+ case T_OP_SUB:
+ case T_OP_CMP_FALSE:
+ mod_s[total].mod_op = LDAP_MOD_DELETE;
break;
+
#ifdef LDAP_MOD_INCREMENT
- case T_OP_INCRM:
- mod_s[total].mod_op = LDAP_MOD_INCREMENT;
+ case T_OP_INCRM:
+ mod_s[total].mod_op = LDAP_MOD_INCREMENT;
break;
#endif
- default:
- radlog(L_ERR, "rlm_ldap (%s): Operator '%s' "
- "is not supported for LDAP modify "
- "operations", inst->xlat_name,
- fr_int2str(fr_tokens, op, "¿unknown?"));
-
- goto error;
+ default:
+ radlog(L_ERR, "rlm_ldap (%s): Operator '%s' "
+ "is not supported for LDAP modify "
+ "operations", inst->xlat_name,
+ fr_int2str(fr_tokens, op, "¿unknown?"));
+
+ goto error;
}
/*
* Perform all modifications as the default admin user.
*/
if (conn->rebound) {
- ldap_errno = ldap_bind_wrapper(&conn,
- inst->login, inst->password,
- TRUE);
+ ldap_errno = ldap_bind_wrapper(&conn, inst->login,
+ inst->password, TRUE);
if (ldap_errno != RLM_MODULE_OK) {
goto error;
}