Example #1
0
/******************************************************************************
 * Global function define                                                     *
 *****************************************************************************/
int gparse_radius_parse(gpacket_info_t *pkt_info, gradius_info_t *radius_info)
{
    uint32_t     code;
    uint8_t     *radius;
    uint8_t     *avp;
    size_t       avp_len;

    radius = gparse_pkt_payload(pkt_info);

    code   = GRADIUS_CODE(radius);
    //We care accounting request only!
    if(code != RADIUS_CODE_ACCT_REQUEST){
        return -1;
    }

    radius_info->hdr        = radius;
    radius_info->code       = code;
    radius_info->avp_bitmap = 0;

    avp     = GRADIUS_AVP(radius);
    avp_len = GRADIUS_LEN(radius) - GRADIUS_HDR_SIZE;
    radius_parse_attr(avp, avp_len, radius_info);

    if(radius_info->avp_bitmap == 0) {
        return -2;
    }

    return 0;
}
Example #2
0
/** Return a VP from the specified request.
 *
 * @param out where to write the pointer to the resolved VP.
 *	Will be NULL if the attribute couldn't be resolved.
 * @param request current request.
 * @param name attribute name including qualifiers.
 * @return -4 if either the attribute or qualifier were invalid, and the same error codes as radius_vpt_get_vp for other
 *	error conditions.
 */
int radius_get_vp(VALUE_PAIR **out, REQUEST *request, char const *name)
{
	value_pair_tmpl_t vpt;

	*out = NULL;

	if (radius_parse_attr(name, &vpt, REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
		return -4;
	}

	return radius_vpt_get_vp(out, request, &vpt);
}
/** Parse qualifiers to convert attrname into a value_pair_tmpl_t.
 *
 * VPTs are used in various places where we need to pre-parse configuration 
 * sections into attribute mappings.
 *
 * @param[in] name attribute name including qualifiers.
 * @param[in] request_def The default request to insert unqualified 
 *	attributes into.
 * @param[in] list_def The default list to insert unqualified attributes into.
 * @return pointer to a value_pair_tmpl_t struct (must be freed with 
 *	radius_tmplfree) or NULL on error.
 */
value_pair_tmpl_t *radius_attr2tmpl(const char *name,
				    request_refs_t request_def,
				    pair_lists_t list_def)
{
	value_pair_tmpl_t *vpt;
	const char *copy = strdup(name);
	
	vpt = rad_calloc(sizeof(value_pair_tmpl_t));
	
	if (radius_parse_attr(copy, vpt, request_def, list_def) < 0) {
		radius_tmplfree(&vpt);
		return NULL;
	}
	
	return vpt;
}
Example #4
0
/** Parse qualifiers to convert attrname into a value_pair_tmpl_t.
 *
 * VPTs are used in various places where we need to pre-parse configuration
 * sections into attribute mappings.
 *
 * @param[in] ctx for talloc
 * @param[in] name attribute name including qualifiers.
 * @param[in] request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] list_def The default list to insert unqualified attributes into.
 * @return pointer to a value_pair_tmpl_t struct (must be freed with
 *	radius_tmplfree) or NULL on error.
 */
value_pair_tmpl_t *radius_attr2tmpl(TALLOC_CTX *ctx, char const *name,
				    request_refs_t request_def,
				    pair_lists_t list_def)
{
	value_pair_tmpl_t *vpt;
	char const *copy;

	vpt = talloc(ctx, value_pair_tmpl_t); /* parse_attr zeroes it */
	copy = talloc_strdup(vpt, name);

	if (radius_parse_attr(copy, vpt, request_def, list_def) < 0) {
		radius_tmplfree(&vpt);
		return NULL;
	}

	return vpt;
}
Example #5
0
/** Parse qualifiers to convert attrname into a VALUE_PAIR_TMPL.
 *
 * VPTs are used in various places where we need to pre-parse configuration 
 * sections into attribute mappings.
 *
 * @param[in] name attribute name including qualifiers.
 * @param[in] request_def The default request to insert unqualified 
 *	attributes into.
 * @param[in] list_def The default list to insert unqualified attributes into.
 * @return pointer to a VALUE_PAIR_TMPL struct (must be freed with 
 *	radius_tmplfree) or NULL on error.
 */
VALUE_PAIR_TMPL *radius_attr2tmpl(const char *name,
				  request_refs_t request_def,
		     		  pair_lists_t list_def)
{
	VALUE_PAIR_TMPL *vpt;
	const char *copy = strdup(name);
	
	vpt = rad_malloc(sizeof(VALUE_PAIR_TMPL));
	memset(vpt, 0, sizeof(VALUE_PAIR_TMPL));
	
	if (radius_parse_attr(copy, vpt, request_def, list_def) < 0) {
		radius_tmplfree(&vpt);
		return NULL;
	}
	
	return vpt;
}
/** Return a VP from the specified request.
 *
 * @param request current request.
 * @param name attribute name including qualifiers.
 * @param vp_p where to write the pointer to the resolved VP. 
 *	Will be NULL if the attribute couldn't be resolved.
 * @return -1 if either the attribute or qualifier were invalid, else 0
 */
int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p)
{
	value_pair_tmpl_t vpt;
	VALUE_PAIR **vps;

	*vp_p = NULL;
	
	if (radius_parse_attr(name, &vpt, REQUEST_CURRENT,
	    PAIR_LIST_REQUEST) < 0) {
		return -1;
	}
	
	if (radius_request(&request, vpt.request) < 0) {
		return 0;
	}
	
	vps = radius_list(request, vpt.list);
	if (!vps) {    
		return 0;
	}
	
	switch (vpt.type)
	{
	/*
	 *	May not may not be found, but it *is* a known name.
	 */
	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;
}
Example #7
0
/** Return a VP from the specified request.
 *
 * @param request current request.
 * @param name attribute name including qualifiers.
 * @param vp_p where to write the pointer to the resolved VP. 
 *	Will be NULL if the attribute couldn't be resolved.
 * @return -1 if either the attribute or qualifier were invalid, else 0
 */
int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p)
{
	VALUE_PAIR_TMPL vpt;
	VALUE_PAIR **vps;

	*vp_p = NULL;
	
	if (radius_parse_attr(name, &vpt, REQUEST_CURRENT,
	    PAIR_LIST_REQUEST) < 0) {
		return -1;
	}
	
	if (radius_request(&request, vpt.request) < 0) {
		RDEBUG("WARNING: Specified request \"%s\" is not available in "
		       "this context", fr_int2str(request_refs, vpt.request,
		       				  "¿unknown?"));
		       
		return 0;
	}
	
	vps = radius_list(request, vpt.list);
	if (!vps) {
		RDEBUG("WARNING: Specified list \"%s\" is not available in "
		       "this context", fr_int2str(pair_lists, vpt.list,
		       				  "¿unknown?"));
	       	       
		return 0;
	}
	
	/*
	 *	May not may not be found, but it *is* a known name.
	 */
	*vp_p = pairfind(*vps, vpt.da->attr, vpt.da->vendor, TAG_ANY);
	
	return 0;
}
Example #8
0
/** Print out attribute info
 *
 * Prints out all instances of a current attribute, or all attributes in a list.
 *
 * At higher debugging levels, also prints out alternative decodings of the same
 * value. This is helpful to determine types for unknown attributes of long
 * passed vendors, or just crazy/broken NAS.
 *
 * It's also useful for exposing issues in the packet decoding functions, as in
 * some cases they get fed random garbage data.
 *
 * This expands to a zero length string.
 */
static ssize_t xlat_debug_attr(UNUSED void *instance, REQUEST *request, char const *fmt,
			       char *out, UNUSED size_t outlen)
{
	VALUE_PAIR *vp, **vps;
	REQUEST *current;
	value_pair_tmpl_t vpt;
	vp_cursor_t cursor;
	char buffer[1024];

	if (!RDEBUG_ENABLED2) {
		*out = '\0';
		return -1;
	}

	while (isspace((int) *fmt)) fmt++;
	if (*fmt == '&') fmt++;

	if (radius_parse_attr(fmt, &vpt, REQUEST_CURRENT, PAIR_LIST_REQUEST) < 0) {
		return -1;
	}

	current = request;
	if (radius_request(&current, vpt.request) < 0) return -2;

	vps = radius_list(current, vpt.list);
	if (!vps) {
		return -2;
	}

	RIDEBUG("Attributes matching \"%s\"", fmt);
	vp = fr_cursor_init(&cursor, vps);

	if (vpt.da) {
		vp = fr_cursor_next_by_num(&cursor, vpt.da->attr, vpt.da->vendor, TAG_ANY);
	}
	while (vp) {
		DICT_ATTR *dac = NULL;
		DICT_VENDOR *dv;
		VALUE_PAIR *vpc = NULL;
		FR_NAME_NUMBER const *type;

		vp_prints_value(buffer, sizeof(buffer), vp, '\'');

		if (vp->da->flags.has_tag) {
			RIDEBUG2("\t%s:%s:%i %s %s",
				fr_int2str(pair_lists, vpt.list, "<INVALID>"),
				vp->da->name,
				vp->tag,
				fr_int2str(fr_tokens, vp->op, "<INVALID>"),
				buffer);
		} else {
			RIDEBUG2("\t%s:%s %s %s",
				fr_int2str(pair_lists, vpt.list, "<INVALID>"),
				vp->da->name,
				fr_int2str(fr_tokens, vp->op, "<INVALID>"),
				buffer);
		}

		if (!RDEBUG_ENABLED3) {
			goto next_vp;
		}

		if (vp->da->vendor) {
			dv = dict_vendorbyvalue(vp->da->vendor);
			RDEBUG3("\t\tvendor        : %i (%s)", vp->da->vendor, dv ? dv->name : "unknown");
		}
		RDEBUG3("\t\ttype          : %s", fr_int2str(dict_attr_types, vp->da->type, "<INVALID>"));
		RDEBUG3("\t\tlength        : %zu", vp->length);

		dac = talloc_memdup(request, vp->da, sizeof(DICT_ATTR));
		if (!dac) {
			return -1;
		}
		dac->flags.vp_free = 0;

		if (!RDEBUG_ENABLED4) {
			goto next_vp;
		}

		type = dict_attr_types;
		while (type->name) {
			int pad;
			ssize_t len;
			uint8_t const *data = NULL;
			vpc = NULL;

			if ((PW_TYPE) type->number == vp->da->type) {
				goto next_type;
			}

			switch (type->number) {
				case PW_TYPE_INVALID:		/* Not real type */
				case PW_TYPE_MAX:		/* Not real type */
				case PW_TYPE_EXTENDED:		/* Not safe/appropriate */
				case PW_TYPE_LONG_EXTENDED:	/* Not safe/appropriate */
				case PW_TYPE_TLV:		/* Not safe/appropriate */
				case PW_TYPE_VSA:		/* @fixme We need special behaviour for these */
					goto next_type;
				default:
					break;
			}

			dac->type = type->number;
			len = rad_vp2data(&data, vp);
			if (len < 0) {
				goto next_type;
			}
			if (data2vp(NULL, NULL, NULL, dac, data, len, len, &vpc) < 0) {
				goto next_type;
			}

			/*
			 *	data2vp has knowledge of expected format lengths, if the length
			 *	from rad_vp2data doesn't match, it encodes the attribute
			 *	as raw octets. This results in many useless debug lines with
			 *	the same hex string.
			 */
			if ((type->number != PW_TYPE_OCTETS) && (vpc->da->type == PW_TYPE_OCTETS)) {
				goto next_type;
			}

			if (!vp_prints_value(buffer, sizeof(buffer), vpc, '\'')) {
				goto next_type;
			}

			if ((pad = (11 - strlen(type->name))) < 0) {
				pad = 0;
			}

			/*
			 *	@fixme: if the value happens to decode as a VSA
			 *	(someone put a VSA into a VSA?), we probably to print
			 *	extended info for that/reparse
			 */
			RDEBUG4("\t\tas %s%*s: %s", type->name, pad, " ", buffer);

			next_type:
			talloc_free(vpc);
			type++;
		}
		next_vp:

		talloc_free(dac);

		if (vpt.da) {
			vp = fr_cursor_next_by_num(&cursor, vpt.da->attr, vpt.da->vendor, TAG_ANY);
		} else {
			vp = fr_cursor_next(&cursor);
		}
	}

	*out = '\0';
	return 0;
}
Example #9
0
/** Convert module specific attribute id to value_pair_tmpl_t.
 *
 * @param[in] ctx for talloc
 * @param[in] name string to convert.
 * @param[in] type Type of quoting around value.
 * @param[in] request_def The default request to insert unqualified
 *	attributes into.
 * @param[in] list_def The default list to insert unqualified attributes into.
 * @return pointer to new VPT.
 */
value_pair_tmpl_t *radius_str2tmpl(TALLOC_CTX *ctx, char const *name, FR_TOKEN type,
				   request_refs_t request_def, pair_lists_t list_def)
{
	int rcode;
	char const *p;
	value_pair_tmpl_t *vpt;
	char buffer[1024];

	vpt = talloc_zero(ctx, value_pair_tmpl_t);
	vpt->name = talloc_typed_strdup(vpt, name);

	switch (type) {
	case T_BARE_WORD:
		/*
		 *	If we can parse it as an attribute, it's an attribute.
		 *	Otherwise, treat it as a literal.
		 */
		rcode = radius_parse_attr(vpt, vpt->name, request_def, list_def);
		if (rcode == -2) {
			talloc_free(vpt);
			return NULL;
		}
		if (rcode == 0) {
			break;
		}
		/* FALL-THROUGH */

	case T_SINGLE_QUOTED_STRING:
		vpt->type = VPT_TYPE_LITERAL;
		break;

	case T_DOUBLE_QUOTED_STRING:
		p = name;
		while (*p) {
			if (*p == '\\') {
				if (!p[1]) break;
				p += 2;
				continue;
			}

			if (*p == '%') break;

			p++;
		}

		/*
		 *	If the double quoted string needs to be
		 *	expanded at run time, make it an xlat
		 *	expansion.  Otherwise, convert it to be a
		 *	literal.
		 */
		if (*p) {
			vpt->type = VPT_TYPE_XLAT;
		} else {
			vpt->type = VPT_TYPE_LITERAL;
		}
		break;

	case T_BACK_QUOTED_STRING:
		vpt->type = VPT_TYPE_EXEC;
		break;

	case T_OP_REG_EQ: /* hack */
		vpt->type = VPT_TYPE_REGEX;
		break;

	default:
		rad_assert(0);
		return NULL;
	}

	radius_tmpl2str(buffer, sizeof(buffer), vpt);

	return vpt;
}