Esempio n. 1
0
/*
 *	Copy data from src to dst, where the attributes are of
 *	different type.
 */
static int do_cast_copy(VALUE_PAIR *dst, VALUE_PAIR const *src)
{
	rad_assert(dst->da->type != src->da->type);

	if (dst->da->type == PW_TYPE_STRING) {
		dst->vp_strvalue = vp_aprint_value(dst, src, false);
		dst->length = strlen(dst->vp_strvalue);
		return 0;
	}

	if (dst->da->type == PW_TYPE_OCTETS) {
		if (src->da->type == PW_TYPE_STRING) {
			pairmemcpy(dst, src->vp_octets, src->length);	/* Copy embedded NULLs */
		} else {
			pairmemcpy(dst, (uint8_t const *) &src->data, src->length);
		}
		return 0;
	}

	if (src->da->type == PW_TYPE_STRING) {
		return pairparsevalue(dst, src->vp_strvalue, 0);
	}

	if ((src->da->type == PW_TYPE_INTEGER64) &&
	    (dst->da->type == PW_TYPE_ETHERNET)) {
		uint8_t array[8];
		uint64_t i;

		i = htonll(src->vp_integer64);
		memcpy(array, &i, 8);

		/*
		 *	For OUIs in the DB.
		 */
		if ((array[0] != 0) || (array[1] != 0)) return -1;

		memcpy(&dst->vp_ether, &array[2], 6);
		dst->length = 6;
		return 0;
	}

	/*
	 *	For integers, we allow the casting of a SMALL type to
	 *	a larger type, but not vice-versa.
	 */
	if (dst->da->type == PW_TYPE_INTEGER64) {
		switch (src->da->type) {
		case PW_TYPE_BYTE:
			dst->vp_integer64 = src->vp_byte;
			break;

		case PW_TYPE_SHORT:
			dst->vp_integer64 = src->vp_short;
			break;

		case PW_TYPE_INTEGER:
			dst->vp_integer64 = src->vp_integer;
			break;

		case PW_TYPE_OCTETS:
			goto do_octets;

		default:
			EVAL_DEBUG("Invalid cast to integer64");
			return -1;

		}
		return 0;
	}

	/*
	 *	We can compare LONG integers to SHORTER ones, so long
	 *	as the long one is on the LHS.
	 */
	if (dst->da->type == PW_TYPE_INTEGER) {
		switch (src->da->type) {
		case PW_TYPE_BYTE:
			dst->vp_integer = src->vp_byte;
			break;

		case PW_TYPE_SHORT:
			dst->vp_integer = src->vp_short;
			break;

		case PW_TYPE_OCTETS:
			goto do_octets;

		default:
			EVAL_DEBUG("Invalid cast to integer");
			return -1;

		}
		return 0;
	}

	if (dst->da->type == PW_TYPE_SHORT) {
		switch (src->da->type) {
		case PW_TYPE_BYTE:
			dst->vp_short = src->vp_byte;
			break;

		case PW_TYPE_OCTETS:
			goto do_octets;

		default:
			EVAL_DEBUG("Invalid cast to short");
			return -1;

		}
		return 0;
	}

	/*
	 *	The attribute we've found has to have a size which is
	 *	compatible with the type of the destination cast.
	 */
	if ((src->length < dict_attr_sizes[dst->da->type][0]) ||
	    (src->length > dict_attr_sizes[dst->da->type][1])) {
		EVAL_DEBUG("Casted attribute is wrong size (%u)", (unsigned int) src->length);
		return -1;
	}

	if (src->da->type == PW_TYPE_OCTETS) {
	do_octets:
		switch (dst->da->type) {
		case PW_TYPE_INTEGER64:
			dst->vp_integer = ntohll(*(uint64_t const *) src->vp_octets);
			break;

		case PW_TYPE_INTEGER:
		case PW_TYPE_DATE:
		case PW_TYPE_SIGNED:
			dst->vp_integer = ntohl(*(uint32_t const *) src->vp_octets);
			break;

		case PW_TYPE_SHORT:
			dst->vp_integer = ntohs(*(uint16_t const *) src->vp_octets);
			break;

		case PW_TYPE_BYTE:
			dst->vp_integer = src->vp_octets[0];
			break;

		default:
			memcpy(&dst->data, src->vp_octets, src->length);
			break;
		}

		dst->length = src->length;
		return 0;
	}

	/*
	 *	Convert host order to network byte order.
	 */
	if ((dst->da->type == PW_TYPE_IPV4_ADDR) &&
	    ((src->da->type == PW_TYPE_INTEGER) ||
	     (src->da->type == PW_TYPE_DATE) ||
	     (src->da->type == PW_TYPE_SIGNED))) {
		dst->vp_ipaddr = htonl(src->vp_integer);

	} else if ((src->da->type == PW_TYPE_IPV4_ADDR) &&
		   ((dst->da->type == PW_TYPE_INTEGER) ||
		    (dst->da->type == PW_TYPE_DATE) ||
		    (dst->da->type == PW_TYPE_SIGNED))) {
		dst->vp_integer = htonl(src->vp_ipaddr);

	} else {		/* they're of the same byte order */
		memcpy(&dst->data, &src->data, src->length);
	}

	dst->length = src->length;

	return 0;
}
Esempio n. 2
0
/** Expand the RHS of a template
 *
 * @note Length of expanded string can be found with talloc_array_length(*out) - 1
 *
 * @param out where to write a pointer to the newly allocated buffer.
 * @param request Current request.
 * @param vpt to evaluate.
 * @return -1 on error, else 0.
 */
int radius_expand_tmpl(char **out, REQUEST *request, value_pair_tmpl_t const *vpt)
{
	VALUE_PAIR *vp;
	*out = NULL;

	rad_assert(vpt->type != TMPL_TYPE_LIST);

	switch (vpt->type) {
	case TMPL_TYPE_LITERAL:
		EVAL_DEBUG("TMPL LITERAL");
		*out = talloc_typed_strdup(request, vpt->name);
		break;

	case TMPL_TYPE_EXEC:
		EVAL_DEBUG("TMPL EXEC");
		*out = talloc_array(request, char, 1024);
		if (radius_exec_program(request, vpt->name, true, false, *out, 1024, EXEC_TIMEOUT, NULL, NULL) != 0) {
			TALLOC_FREE(*out);
			return -1;
		}
		break;

	case TMPL_TYPE_REGEX:
		EVAL_DEBUG("TMPL REGEX");
		/* Error in expansion, this is distinct from zero length expansion */
		if (radius_axlat(out, request, vpt->name, NULL, NULL) < 0) {
			rad_assert(!*out);
			return -1;
		}
		break;

	case TMPL_TYPE_XLAT:
		EVAL_DEBUG("TMPL XLAT");
		/* Error in expansion, this is distinct from zero length expansion */
		if (radius_axlat(out, request, vpt->name, NULL, NULL) < 0) {
			rad_assert(!*out);
			return -1;
		}
		break;

	case TMPL_TYPE_XLAT_STRUCT:
		EVAL_DEBUG("TMPL XLAT_STRUCT");
		/* Error in expansion, this is distinct from zero length expansion */
		if (radius_axlat_struct(out, request, vpt->tmpl_xlat, NULL, NULL) < 0) {
			rad_assert(!*out);
			return -1;
		}
		RDEBUG2("EXPAND %s", vpt->name); /* xlat_struct doesn't do this */
		RDEBUG2("   --> %s", *out);
		break;

	case TMPL_TYPE_ATTR:
	{
		int ret;

		EVAL_DEBUG("TMPL ATTR");
		ret = tmpl_find_vp(&vp, request, vpt);
		if (ret < 0) return -2;

		*out = vp_aprint_value(request, vp, false);
		if (!*out) return -1;
	}
		break;

	case TMPL_TYPE_DATA:
	case TMPL_TYPE_REGEX_STRUCT:
		rad_assert(0 == 1);
		/* FALL-THROUGH */

	default:
		break;
	}

	EVAL_DEBUG("Expand tmpl --> %s", *out);
	return 0;
}
Esempio n. 3
0
/**  Print a template to a string
 *
 * @param[out] buffer for the output string
 * @param[in] bufsize of the buffer
 * @param[in] vpt to print
 * @return the size of the string printed
 */
size_t radius_tmpl2str(char *buffer, size_t bufsize, value_pair_tmpl_t const *vpt)
{
	size_t len;
	char c;
	char const *p;
	char *q = buffer;
	char *end;

	if (!vpt) {
		*buffer = '\0';
		return 0;
	}

	switch (vpt->type) {
	default:
		return 0;

	case VPT_TYPE_REGEX:
	case VPT_TYPE_REGEX_STRUCT:
		c = '/';
		break;

	case VPT_TYPE_XLAT:
	case VPT_TYPE_XLAT_STRUCT:
		c = '"';
		break;

	case VPT_TYPE_LIST:
	case VPT_TYPE_LITERAL:	/* single-quoted or bare word */
		/*
		 *	Hack
		 */
		for (p = vpt->name; *p != '\0'; p++) {
			if (*p == ' ') break;
			if (*p == '\'') break;
			if (!dict_attr_allowed_chars[(int) *p]) break;
		}

		if (!*p) {
			strlcpy(buffer, vpt->name, bufsize);
			return strlen(buffer);
		}

		c = '\'';
		break;

	case VPT_TYPE_EXEC:
		c = '`';
		break;

	case VPT_TYPE_ATTR:
		buffer[0] = '&';
		if (vpt->vpt_request == REQUEST_CURRENT) {
			if (vpt->vpt_list == PAIR_LIST_REQUEST) {
				strlcpy(buffer + 1, vpt->vpt_da->name, bufsize - 1);
			} else {
				snprintf(buffer + 1, bufsize - 1, "%s:%s",
					 fr_int2str(pair_lists, vpt->vpt_list, ""),
					 vpt->vpt_da->name);
			}

		} else {
			snprintf(buffer + 1, bufsize - 1, "%s.%s:%s",
				 fr_int2str(request_refs, vpt->vpt_request, ""),
				 fr_int2str(pair_lists, vpt->vpt_list, ""),
				 vpt->vpt_da->name);
		}

		len = strlen(buffer);

		if ((vpt->vpt_tag == TAG_ANY) && (vpt->vpt_num == NUM_ANY)) {
			return len;
		}

		q = buffer + len;
		bufsize -= len;

		if (vpt->vpt_tag != TAG_ANY) {
			snprintf(q, bufsize, ":%d", vpt->vpt_tag);
			len = strlen(q);
			q += len;
			bufsize -= len;
		}

		if (vpt->vpt_num != NUM_ANY) {
			snprintf(q, bufsize, "[%u]", vpt->vpt_num);
			len = strlen(q);
			q += len;
		}

		return (q - buffer);

	case VPT_TYPE_DATA:
		if (vpt->vpt_value) {
			VALUE_PAIR *vp;
			TALLOC_CTX *ctx;

			memcpy(&ctx, &vpt, sizeof(ctx)); /* hack */

			MEM(vp = pairalloc(ctx, vpt->vpt_da));
			memcpy(&vp->data, vpt->vpt_value, sizeof(vp->data));
			vp->length = vpt->vpt_length;

			q = vp_aprint_value(vp, vp);

			if ((vpt->vpt_da->type != PW_TYPE_STRING) &&
			    (vpt->vpt_da->type != PW_TYPE_DATE)) {
				strlcpy(buffer, q, bufsize);
			} else {
				/*
				 *	FIXME: properly escape the string...
				 */
				snprintf(buffer, bufsize, "\"%s\"", q);
			}

			talloc_free(q);
			pairfree(&vp);
			return strlen(buffer);

		} else {
			*buffer = '\0';
			return 0;
		}
	}

	if (bufsize <= 3) {
	no_room:
		*buffer = '\0';
		return 0;
	}

	p = vpt->name;
	*(q++) = c;
	end = buffer + bufsize - 3; /* quotes + EOS */

	while (*p && (q < end)) {
		if (*p == c) {
			if ((end - q) < 4) goto no_room; /* escape, char, quote, EOS */
			*(q++) = '\\';
			*(q++) = *(p++);
			continue;
		}

		switch (*p) {
		case '\\':
			if ((end - q) < 4) goto no_room;
			*(q++) = '\\';
			*(q++) = *(p++);
			break;

		case '\r':
			if ((end - q) < 4) goto no_room;
			*(q++) = '\\';
			*(q++) = 'r';
			p++;
			break;

		case '\n':
			if ((end - q) < 4) goto no_room;
			*(q++) = '\\';
			*(q++) = 'r';
			p++;
			break;

		case '\t':
			if ((end - q) < 4) goto no_room;
			*(q++) = '\\';
			*(q++) = 't';
			p++;
			break;

		default:
			*(q++) = *(p++);
			break;
		}
	}

	*(q++) = c;
	*q = '\0';

	return q - buffer;
}