Пример #1
0
/** Convert attribute map into valuepairs
 *
 * Use the attribute map built earlier to convert LDAP values into valuepairs and insert them into whichever
 * list they need to go into.
 *
 * This is *NOT* atomic, but there's no condition for which we should error out...
 *
 * @param[in] inst rlm_ldap configuration.
 * @param[in] request Current request.
 * @param[in] handle associated with entry.
 * @param[in] expanded attributes (rhs of map).
 * @param[in] entry to retrieve attributes from.
 * @return
 *	- Number of maps successfully applied.
 *	- -1 on failure.
 */
int rlm_ldap_map_do(const rlm_ldap_t *inst, REQUEST *request, LDAP *handle,
		    rlm_ldap_map_exp_t const *expanded, LDAPMessage *entry)
{
	vp_map_t const 	*map;
	unsigned int		total = 0;
	int			applied = 0;	/* How many maps have been applied to the current request */

	rlm_ldap_result_t	result;
	char const		*name;

	RINDENT();
	for (map = expanded->maps; map != NULL; map = map->next) {
		int ret;

		name = expanded->attrs[total++];

		/*
		 *	Binary safe
		 */
		result.values = ldap_get_values_len(handle, entry, name);
		if (!result.values) {
			RDEBUG3("Attribute \"%s\" not found in LDAP object", name);

			goto next;
		}

		/*
		 *	Find out how many values there are for the
		 *	attribute and extract all of them.
		 */
		result.count = ldap_count_values_len(result.values);

		/*
		 *	If something bad happened, just skip, this is probably
		 *	a case of the dst being incorrect for the current
		 *	request context
		 */
		ret = map_to_request(request, map, rlm_ldap_map_getvalue, &result);
		if (ret == -1) return -1;	/* Fail */

		/*
		 *	How many maps we've processed
		 */
		applied++;

	next:
		ldap_value_free_len(result.values);
	}
	REXDENT();

	/*
	 *	Retrieve any valuepair attributes from the result, these are generic values specifying
	 *	a radius list, operator and value.
	 */
	if (inst->valuepair_attr) {
		struct berval	**values;
		int		count, i;

		values = ldap_get_values_len(handle, entry, inst->valuepair_attr);
		count = ldap_count_values_len(values);

		RINDENT();
		for (i = 0; i < count; i++) {
			vp_map_t *attr;
			char *value;

			value = rlm_ldap_berval_to_string(request, values[i]);
			RDEBUG3("Parsing attribute string '%s'", value);
			if (map_afrom_attr_str(request, &attr, value,
					       REQUEST_CURRENT, PAIR_LIST_REPLY,
					       REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
				RWDEBUG("Failed parsing '%s' value \"%s\" as valuepair (%s), skipping...",
					fr_strerror(), inst->valuepair_attr, value);
				talloc_free(value);
				continue;
			}
			if (map_to_request(request, attr, map_to_vp, NULL) < 0) {
				RWDEBUG("Failed adding \"%s\" to request, skipping...", value);
			} else {
				applied++;
			}
			talloc_free(attr);
			talloc_free(value);
		}
		REXDENT();
		ldap_value_free_len(values);
	}

	return applied;
}
Пример #2
0
/** Callback for map_to_request
 *
 * Performs exactly the same job as map_to_vp, but pulls attribute values from LDAP entries
 *
 * @see map_to_vp
 */
int rlm_ldap_map_getvalue(TALLOC_CTX *ctx, VALUE_PAIR **out, REQUEST *request, vp_map_t const *map, void *uctx)
{
	rlm_ldap_result_t *self = uctx;
	VALUE_PAIR *head = NULL, *vp;
	vp_cursor_t cursor;
	int i;

	fr_cursor_init(&cursor, &head);

	switch (map->lhs->type) {
	/*
	 *	This is a mapping in the form of:
	 *		<list>: += <ldap attr>
	 *
	 *	Where <ldap attr> is:
	 *		<list>:<attr> <op> <value>
	 *
	 *	It is to allow for legacy installations which stored
	 *	RADIUS control and reply attributes in separate LDAP
	 *	attributes.
	 */
	case TMPL_TYPE_LIST:
		for (i = 0; i < self->count; i++) {
			vp_map_t *attr = NULL;

			RDEBUG3("Parsing valuepair string \"%s\"", self->values[i]->bv_val);
			if (map_afrom_attr_str(ctx, &attr, self->values[i]->bv_val,
					       map->lhs->tmpl_request, map->lhs->tmpl_list,
					       REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
				RWDEBUG("Failed parsing \"%s\" as valuepair (%s), skipping...", fr_strerror(),
					self->values[i]->bv_val);
				continue;
			}

			if (attr->lhs->tmpl_request != map->lhs->tmpl_request) {
				RWDEBUG("valuepair \"%s\" has conflicting request qualifier (%s vs %s), skipping...",
					self->values[i]->bv_val,
					fr_int2str(request_refs, attr->lhs->tmpl_request, "<INVALID>"),
					fr_int2str(request_refs, map->lhs->tmpl_request, "<INVALID>"));
			next_pair:
				talloc_free(attr);
				continue;
			}

			if ((attr->lhs->tmpl_list != map->lhs->tmpl_list)) {
				RWDEBUG("valuepair \"%s\" has conflicting list qualifier (%s vs %s), skipping...",
					self->values[i]->bv_val,
					fr_int2str(pair_lists, attr->lhs->tmpl_list, "<INVALID>"),
					fr_int2str(pair_lists, map->lhs->tmpl_list, "<INVALID>"));
				goto next_pair;
			}

			if (map_to_vp(request, &vp, request, attr, NULL) < 0) {
				RWDEBUG("Failed creating attribute for valuepair \"%s\", skipping...",
					self->values[i]->bv_val);
				goto next_pair;
			}

			fr_cursor_merge(&cursor, vp);
			talloc_free(attr);

			/*
			 *	Only process the first value, unless the operator is +=
			 */
			if (map->op != T_OP_ADD) break;
		}
		break;

	/*
	 *	Iterate over all the retrieved values,
	 *	don't try and be clever about changing operators
	 *	just use whatever was set in the attribute map.
	 */
	case TMPL_TYPE_ATTR:
		for (i = 0; i < self->count; i++) {
			if (!self->values[i]->bv_len) continue;

			vp = pairalloc(ctx, map->lhs->tmpl_da);
			rad_assert(vp);

			if (pairparsevalue(vp, self->values[i]->bv_val, self->values[i]->bv_len) < 0) {
				char *escaped;

				escaped = fr_aprints(vp, self->values[i]->bv_val, self->values[i]->bv_len, '"');
				RWDEBUG("Failed parsing value \"%s\" for attribute %s: %s", escaped,
					map->lhs->tmpl_da->name, fr_strerror());

				talloc_free(vp); /* also frees escaped */
				continue;
			}

			vp->op = map->op;
			fr_cursor_insert(&cursor, vp);

			/*
			 *	Only process the first value, unless the operator is +=
			 */
			if (map->op != T_OP_ADD) break;
		}
		break;

	default:
		rad_assert(0);
	}

	*out = head;

	return 0;
}
Пример #3
0
/** Converts a serialized cache entry back into a structure
 *
 * @param c Cache entry to populate (should already be allocated)
 * @param in String representation of cache entry.
 * @param inlen Length of string. May be < 0 in which case strlen will be
 *	used to calculate the length of the string.
 * @return 0 on success, -1 on error.
 */
int cache_deserialize(rlm_cache_entry_t *c, char *in, ssize_t inlen)
{
	vp_cursor_t packet, control, reply;

	TALLOC_CTX *store = NULL;
	char *p, *q;

	store = talloc_pool(c, 1024);
	if (!store) return -1;

	if (inlen < 0) inlen = strlen(in);

	fr_cursor_init(&packet, &c->packet);
	fr_cursor_init(&control, &c->control);
	fr_cursor_init(&reply, &c->reply);

	p = in;

	while (((size_t)(p - in)) < (size_t)inlen) {
		value_pair_map_t *map = NULL;
		VALUE_PAIR *vp = NULL;
		ssize_t len;

		q = strchr(p, '\n');
		if (!q) break;	/* List should also be terminated with a \n */
		*q = '\0';

		if (map_afrom_attr_str(store, &map, p,
				       REQUEST_CURRENT, PAIR_LIST_REQUEST,
				       REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
			fr_strerror_printf("Failed parsing pair: %s", p);
			goto error;
		}

		if (map->lhs->type != TMPL_TYPE_ATTR) {
			fr_strerror_printf("Pair left hand side \"%s\" parsed as %s, needed attribute.  "
					   "Check local dictionaries", map->lhs->name,
					   fr_int2str(tmpl_names, map->lhs->type, "<INVALID>"));
			goto error;
		}

		if (map->rhs->type != TMPL_TYPE_LITERAL) {
			fr_strerror_printf("Pair right hand side \"%s\" parsed as %s, needed literal.  "
					   "Check serialized data quoting", map->rhs->name,
					   fr_int2str(tmpl_names, map->rhs->type, "<INVALID>"));
			goto error;
		}

		/*
		 *	Convert literal to a type appropriate for
		 *	the VP.
		 */
		if (tmpl_cast_in_place(map->rhs, map->lhs->tmpl_da->type, map->lhs->tmpl_da) < 0) goto error;

		vp = pairalloc(c, map->lhs->tmpl_da);
		len = value_data_copy(vp, &vp->data, map->rhs->tmpl_data_type,
				      &map->rhs->tmpl_data_value, map->rhs->tmpl_data_length);
		if (len < 0) goto error;

		/*
		 *	Pull out the special attributes, and set the
		 *	relevant cache entry fields.
		 */
		if (vp->da->vendor == 0) switch (vp->da->attr) {
		case PW_CACHE_CREATED:
			c->created = vp->vp_date;
			talloc_free(vp);
			goto next;

		case PW_CACHE_EXPIRES:
			c->expires = vp->vp_date;
			talloc_free(vp);
			goto next;

		default:
			break;
		}

		switch (map->lhs->tmpl_list) {
		case PAIR_LIST_REQUEST:
			fr_cursor_insert(&packet, vp);
			break;

		case PAIR_LIST_CONTROL:
			fr_cursor_insert(&control, vp);
			break;

		case PAIR_LIST_REPLY:
			fr_cursor_insert(&reply, vp);
			break;

		default:
			fr_strerror_printf("Invalid cache list for pair: %s", p);
		error:
			talloc_free(vp);
			talloc_free(map);
			return -1;
		}
	next:
		p = q + 1;
		talloc_free(map);
	}

	return 0;
}