Example #1
0
static VALUE_PAIR *rlm_ldap_map_getvalue(REQUEST *request, value_pair_map_t const *map, void *ctx)
{
	rlm_ldap_result_t *self = ctx;
	VALUE_PAIR *head = NULL, *vp;
	vp_cursor_t out;
	int i;
	
	paircursor(&out, &head);
	
	/*
	 *	Iterate over all the retrieved values,
	 *	don't try and be clever about changing operators
	 *	just use whatever was set in the attribute map.	
	 */
	for (i = 0; i < self->count; i++) {
		vp = pairalloc(request, map->dst->da);
		rad_assert(vp);

		if (!pairparsevalue(vp, self->values[i])) {
			RDEBUG("Failed parsing value for \"%s\"", map->dst->da->name);
			
			pairbasicfree(vp);
			continue;
		}
		
		vp->op = map->op;
		pairinsert(&out, vp);
	}
	
	return head;		
}
Example #2
0
static void cleanresp(RADIUS_PACKET *resp)
{
	VALUE_PAIR *vpnext, *vp, **last;


	/*
	 * maybe should just copy things we care about, or keep
	 * a copy of the original input and start from there again?
	 */
	pairdelete(&resp->vps, PW_EAP_MESSAGE, 0, TAG_ANY);
	pairdelete(&resp->vps, ATTRIBUTE_EAP_BASE+PW_EAP_IDENTITY, 0, TAG_ANY);

	last = &resp->vps;
	for(vp = *last; vp != NULL; vp = vpnext)
	{
		vpnext = vp->next;

		if((vp->da->attribute > ATTRIBUTE_EAP_BASE &&
		    vp->da->attribute <= ATTRIBUTE_EAP_BASE+256) ||
		   (vp->da->attribute > ATTRIBUTE_EAP_SIM_BASE &&
		    vp->da->attribute <= ATTRIBUTE_EAP_SIM_BASE+256))
		{
			*last = vpnext;
			pairbasicfree(vp);
		} else {
			last = &vp->next;
		}
	}
}
Example #3
0
/** Replace all matching VPs
 *
 * Walks over 'first', and replaces the first VP that matches 'replace'.
 *
 * @note Memory used by the VP being replaced will be freed.
 * @note Will not work with unknown attributes.
 *
 * @param[in,out] first VP in linked list. Will search and replace in this list.
 * @param[in] replace VP to replace.
 * @return a copy of the input vp
 */
void pairreplace(VALUE_PAIR **first, VALUE_PAIR *replace)
{
	VALUE_PAIR *i, *next;
	VALUE_PAIR **prev = first;

	VERIFY(replace);

	if (*first == NULL) {
		*first = replace;
		return;
	}

	/*
	 *	Not an empty list, so find item if it is there, and
	 *	replace it. Note, we always replace the first one, and
	 *	we ignore any others that might exist.
	 */
	for(i = *first; i; i = next) {
		VERIFY(i);
		next = i->next;

		/*
		 *	Found the first attribute, replace it,
		 *	and return.
		 */
		if ((i->da == replace->da) &&
		    (!i->da->flags.has_tag || (i->tag == replace->tag))
		) {
			*prev = replace;

			/*
			 *	Should really assert that replace->next == NULL
			 */
			replace->next = next;
			pairbasicfree(i);
			return;
		}

		/*
		 *	Point to where the attribute should go.
		 */
		prev = &i->next;
	}

	/*
	 *	If we got here, we didn't find anything to replace, so
	 *	stopped at the last item, which we just append to.
	 */
	*prev = replace;
}
Example #4
0
/*
 *	Delete the pair(s) with the matching attribute
 */
void pairdelete(VALUE_PAIR **first, int attr)
{
	VALUE_PAIR *i, *next;
	VALUE_PAIR **last = first;

	for(i = *first; i; i = next) {
		next = i->next;
		if (i->attribute == attr) {
			*last = next;
			pairbasicfree(i);
		} else {
			last = &i->next;
		}
	}
}
Example #5
0
/*
 *	Release the memory used by a list of attribute-value
 *	pairs, and sets the pair pointer to NULL.
 */
void pairfree(VALUE_PAIR **pair_ptr)
{
	VALUE_PAIR	*next, *pair;

	if (!pair_ptr) return;
	pair = *pair_ptr;

	while (pair != NULL) {
		next = pair->next;
		pairbasicfree(pair);
		pair = next;
	}

	*pair_ptr = NULL;
}
Example #6
0
/*
 *	Delete the pair(s) with the matching attribute
 */
void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor)
{
	VALUE_PAIR *i, *next;
	VALUE_PAIR **last = first;

	for(i = *first; i; i = next) {
		next = i->next;
		if ((i->attribute == attr) && (i->vendor == vendor)) {
			*last = next;
			pairbasicfree(i);
		} else {
			last = &i->next;
		}
	}
}
Example #7
0
/** Copy a single valuepair
 *
 * Allocate a new valuepair and copy the da from the old vp.
 *
 * @param[in] ctx for talloc
 * @param[in] vp to copy.
 * @return a copy of the input VP or NULL on error.
 */
VALUE_PAIR *paircopyvp(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
{
	VALUE_PAIR *n;

	if (!vp) return NULL;

	VERIFY(vp);

	n = pairalloc(ctx, vp->da);
	if (!n) {
		fr_strerror_printf("out of memory");
		return NULL;
	}
	
	memcpy(n, vp, sizeof(*n));
	
	/*
	 *	Now copy the value
	 */
	if (vp->type == VT_XLAT) {
		n->value.xlat = talloc_strdup(n, n->value.xlat);
	}
	
	n->da = dict_attr_copy(vp->da, true);
	if (!n->da) {
		pairbasicfree(n);
		return NULL;
	}
	
	n->next = NULL;

	if ((n->da->type == PW_TYPE_TLV) ||
	    (n->da->type == PW_TYPE_OCTETS)) {
		if (n->vp_octets != NULL) {
			n->vp_octets = talloc_memdup(n, vp->vp_octets, n->length);
		}

	} else if (n->da->type == PW_TYPE_STRING) {
		if (n->vp_strvalue != NULL) {
			/*
			 *	Equivalent to, and faster than strdup.
			 */
			n->vp_strvalue = talloc_memdup(n, vp->vp_octets, n->length + 1);
		}
	}

	return n;
}
Example #8
0
/** Free memory used by a valuepair list.
 *
 * @todo TLV: needs to free all dependents of each VP freed.
 */
void pairfree(VALUE_PAIR **vps)
{
	VALUE_PAIR	*next, *vp;

	if (!vps) return;
	vp = *vps;

	while (vp) {
		VERIFY(vp);
		next = vp->next;
		pairbasicfree(vp);
		vp = next;
	}

	*vps = NULL;
}
Example #9
0
/** Delete matching pairs
 *
 * Delete matching pairs from the attribute list.
 * 
 * @param[in+out] vp which is head of the list.
 * @param[in] attr to match.
 * @param[in] vendor to match.
 * @param[in] tag to match, only used if > 0.
 */
void pairdelete(VALUE_PAIR **first, unsigned int attr, unsigned int vendor,
		int8_t tag)
{
	VALUE_PAIR *i, *next;
	VALUE_PAIR **last = first;

	for(i = *first; i; i = next) {
		next = i->next;
		if ((i->attribute == attr) && (i->vendor == vendor) &&
		    ((tag < 0) ||
		     (i->flags.has_tag && (i->flags.tag == tag)))) {
			*last = next;
			pairbasicfree(i);
		} else {
			last = &i->next;
		}
	}
}
Example #10
0
/*
 *	Create a VALUE_PAIR from an ASCII attribute and value.
 */
VALUE_PAIR *pairmake(const char *attribute, const char *value, int operator)
{
	DICT_ATTR	*da;
	VALUE_PAIR	*vp;
	char            *tc, *ts;
	signed char     tag;
	int             found_tag;
	char		buffer[64];
	const char	*attrname = attribute;

	/*
	 *    Check for tags in 'Attribute:Tag' format.
	 */
	found_tag = 0;
	tag = 0;

	ts = strrchr(attribute, ':');
	if (ts && !ts[1]) {
		fr_strerror_printf("Invalid tag for attribute %s", attribute);
		return NULL;
	}

	if (ts && ts[1]) {
		strlcpy(buffer, attribute, sizeof(buffer));
		attrname = buffer;
		ts = strrchr(attrname, ':');

	         /* Colon found with something behind it */
	         if (ts[1] == '*' && ts[2] == 0) {
		         /* Wildcard tag for check items */
		         tag = TAG_ANY;
			 *ts = 0;
		 } else if ((ts[1] >= '0') && (ts[1] <= '9')) {
		         /* It's not a wild card tag */
		         tag = strtol(ts + 1, &tc, 0);
			 if (tc && !*tc && TAG_VALID_ZERO(tag))
				 *ts = 0;
			 else tag = 0;
		 } else {
			 fr_strerror_printf("Invalid tag for attribute %s", attribute);
			 return NULL;
		 }
		 found_tag = 1;
	}

	/*
	 *	It's not found in the dictionary, so we use
	 *	another method to create the attribute.
	 */
	if ((da = dict_attrbyname(attrname)) == NULL) {
		return pairmake_any(attrname, value, operator);
	}

	if ((vp = pairalloc(da)) == NULL) {
		fr_strerror_printf("out of memory");
		return NULL;
	}
	vp->operator = (operator == 0) ? T_OP_EQ : operator;

	/*      Check for a tag in the 'Merit' format of:
	 *      :Tag:Value.  Print an error if we already found
	 *      a tag in the Attribute.
	 */

	if (value && (*value == ':' && da->flags.has_tag)) {
	        /* If we already found a tag, this is invalid */
	        if(found_tag) {
			fr_strerror_printf("Duplicate tag %s for attribute %s",
				   value, vp->name);
			DEBUG("Duplicate tag %s for attribute %s\n",
				   value, vp->name);
		        pairbasicfree(vp);
			return NULL;
		}
	        /* Colon found and attribute allows a tag */
	        if (value[1] == '*' && value[2] == ':') {
		       /* Wildcard tag for check items */
		       tag = TAG_ANY;
		       value += 3;
		} else {
	               /* Real tag */
		       tag = strtol(value + 1, &tc, 0);
		       if (tc && *tc==':' && TAG_VALID_ZERO(tag))
			    value = tc + 1;
		       else tag = 0;
		}
		found_tag = 1;
	}

	if (found_tag) {
	  vp->flags.tag = tag;
	}

	switch (vp->operator) {
	default:
		break;

		/*
		 *      For =* and !* operators, the value is irrelevant
		 *      so we return now.
		 */
	case T_OP_CMP_TRUE:
	case T_OP_CMP_FALSE:
		vp->vp_strvalue[0] = '\0';
		vp->length = 0;
	        return vp;
		break;

		/*
		 *	Regular expression comparison of integer attributes
		 *	does a STRING comparison of the names of their
		 *	integer attributes.
		 */
	case T_OP_REG_EQ:	/* =~ */
	case T_OP_REG_NE:	/* !~ */
		if (!value) {
			fr_strerror_printf("No regular expression found in %s",
					   vp->name);
		        pairbasicfree(vp);
			return NULL;
		}
	  
		strlcpy(vp->vp_strvalue, value, sizeof(vp->vp_strvalue));
		vp->length = strlen(vp->vp_strvalue);
		/*
		 *	If anything goes wrong, this is a run-time error,
		 *	not a compile-time error.
		 */
		return vp;

	}

	/*
	 *	FIXME: if (strcasecmp(attribute, vp->name) != 0)
	 *	then the user MAY have typed in the attribute name
	 *	as Vendor-%d-Attr-%d, and the value MAY be octets.
	 *
	 *	We probably want to fix pairparsevalue to accept
	 *	octets as values for any attribute.
	 */
	if (value && (pairparsevalue(vp, value) == NULL)) {
		pairbasicfree(vp);
		return NULL;
	}

	return vp;
}
static int do_attr_rewrite(void *instance, REQUEST *request)
{
	rlm_attr_rewrite_t *data = (rlm_attr_rewrite_t *) instance;
	int ret = RLM_MODULE_NOOP;
	VALUE_PAIR *attr_vp = NULL;
	VALUE_PAIR *tmp = NULL;
	regex_t preg;
	regmatch_t pmatch[9];
	int cflags = 0;
	int err = 0;
	char done_xlat = 0;
	unsigned int len = 0;
	char err_msg[MAX_STRING_LEN];
	unsigned int i = 0;
	unsigned int j = 0;
	unsigned int counter = 0;
	char new_str[MAX_STRING_LEN];
	char *ptr, *ptr2;
	char search_STR[MAX_STRING_LEN];
	char replace_STR[MAX_STRING_LEN];

	if ((attr_vp = pairfind(request->config_items, PW_REWRITE_RULE)) != NULL){
		if (data->name == NULL || strcmp(data->name,attr_vp->vp_strvalue))
			return RLM_MODULE_NOOP;
	}

	if (data->new_attr){
		/* new_attribute = yes */
		if (!radius_xlat(replace_STR, sizeof(replace_STR), data->replace, request, NULL)) {
			DEBUG2("%s: xlat on replace string failed.", data->name);
			return ret;
		}
		attr_vp = pairmake(data->attribute,replace_STR,0);
		if (attr_vp == NULL){
			DEBUG2("%s: Could not add new attribute %s with value '%s'", data->name,
				data->attribute,replace_STR);
			return ret;
		}
		switch(data->searchin){
			case RLM_REGEX_INPACKET:
				pairadd(&request->packet->vps,attr_vp);
				break;
			case RLM_REGEX_INCONFIG:
				pairadd(&request->config_items,attr_vp);
				break;
			case RLM_REGEX_INREPLY:
				pairadd(&request->reply->vps,attr_vp);
				break;
			case RLM_REGEX_INPROXY:
				if (!request->proxy) {
					pairbasicfree(attr_vp);
					return RLM_MODULE_NOOP;
				}
				pairadd(&request->proxy->vps, attr_vp);
				break;
			case RLM_REGEX_INPROXYREPLY:
				if (!request->proxy_reply) {
					pairbasicfree(attr_vp);
					return RLM_MODULE_NOOP;
				}
				pairadd(&request->proxy_reply->vps, attr_vp);
				break;
			default:
				radlog(L_ERR, "%s: Illegal value for searchin. Changing to packet.", data->name);
				data->searchin = RLM_REGEX_INPACKET;
				pairadd(&request->packet->vps,attr_vp);
				break;
		}
		DEBUG2("%s: Added attribute %s with value '%s'", data->name,data->attribute,replace_STR);
		ret = RLM_MODULE_OK;
	} else {
		int replace_len = 0;

		/* new_attribute = no */
		switch (data->searchin) {
			case RLM_REGEX_INPACKET:
				if (data->attr_num == PW_USER_NAME)
					attr_vp = request->username;
				else if (data->attr_num == PW_USER_PASSWORD)
					attr_vp = request->password;
				else
					tmp = request->packet->vps;
				break;
			case RLM_REGEX_INCONFIG:
				tmp = request->config_items;
				break;
			case RLM_REGEX_INREPLY:
				tmp = request->reply->vps;
				break;
			case RLM_REGEX_INPROXYREPLY:
				if (!request->proxy_reply)
					return RLM_MODULE_NOOP;
				tmp = request->proxy_reply->vps;
				break;
			case RLM_REGEX_INPROXY:
				if (!request->proxy)
					return RLM_MODULE_NOOP;
				tmp = request->proxy->vps;
				break;
			default:
				radlog(L_ERR, "%s: Illegal value for searchin. Changing to packet.", data->name);
				data->searchin = RLM_REGEX_INPACKET;
				attr_vp = pairfind(request->packet->vps, data->attr_num);
				break;
		}
do_again:
		if (tmp != NULL)
			attr_vp = pairfind(tmp, data->attr_num);
		if (attr_vp == NULL) {
			DEBUG2("%s: Could not find value pair for attribute %s", data->name,data->attribute);
			return ret;
		}
		if (attr_vp->vp_strvalue == NULL || attr_vp->length == 0){
			DEBUG2("%s: Attribute %s string value NULL or of zero length", data->name,data->attribute);
			return ret;
		}
		cflags |= REG_EXTENDED;
		if (data->nocase)
			cflags |= REG_ICASE;

		if (!radius_xlat(search_STR, sizeof(search_STR), data->search, request, NULL) && data->search_len != 0) {
			DEBUG2("%s: xlat on search string failed.", data->name);
			return ret;
		}

		if ((err = regcomp(&preg,search_STR,cflags))) {
			regerror(err, &preg, err_msg, MAX_STRING_LEN);
			DEBUG2("%s: regcomp() returned error: %s", data->name,err_msg);
			return ret;
		}

		if ((attr_vp->type == PW_TYPE_IPADDR) &&
		    (attr_vp->vp_strvalue[0] == '\0')) {
			inet_ntop(AF_INET, &(attr_vp->vp_ipaddr),
				  attr_vp->vp_strvalue,
				  sizeof(attr_vp->vp_strvalue));
		}

		ptr = new_str;
		ptr2 = attr_vp->vp_strvalue;
		counter = 0;

		for ( i = 0 ;i < (unsigned)data->num_matches; i++) {
			err = regexec(&preg, ptr2, REQUEST_MAX_REGEX, pmatch, 0);
			if (err == REG_NOMATCH) {
				if (i == 0) {
					DEBUG2("%s: Does not match: %s = %s", data->name,
							data->attribute, attr_vp->vp_strvalue);
					regfree(&preg);
					goto to_do_again;
				} else
					break;
			}
			if (err != 0) {
				regfree(&preg);
				radlog(L_ERR, "%s: match failure for attribute %s with value '%s'", data->name,
						data->attribute, attr_vp->vp_strvalue);
				return ret;
			}
			if (pmatch[0].rm_so == -1)
				break;
			len = pmatch[0].rm_so;
			if (data->append) {
				len = len + (pmatch[0].rm_eo - pmatch[0].rm_so);
			}
			counter += len;
			if (counter >= MAX_STRING_LEN) {
				regfree(&preg);
				DEBUG2("%s: Replacement out of limits for attribute %s with value '%s'", data->name,
						data->attribute, attr_vp->vp_strvalue);
				return ret;
			}

			memcpy(ptr, ptr2,len);
			ptr += len;
			*ptr = '\0';
			ptr2 += pmatch[0].rm_eo;

			if (i == 0){
				/*
				 * We only run on the first match, sorry
				 */
				for(j = 0; j <= REQUEST_MAX_REGEX; j++){
					char *p;
					char buffer[sizeof(attr_vp->vp_strvalue)];

					/*
				   	 * Stolen from src/main/valuepair.c, paircompare()
				 	 */

					/*
					 * Delete old matches if the corresponding match does not
					 * exist in the current regex
					 */
					if (pmatch[j].rm_so == -1){
						p = request_data_get(request,request,REQUEST_DATA_REGEX | j);
						if (p){
							free(p);
							continue;
						}
						break;
					}
					memcpy(buffer,
					       attr_vp->vp_strvalue + pmatch[j].rm_so,
					       pmatch[j].rm_eo - pmatch[j].rm_so);
					buffer[pmatch[j].rm_eo - pmatch[j].rm_so] = '\0';
					p = strdup(buffer);
					request_data_add(request,request,REQUEST_DATA_REGEX | j,p,free);
				}
			}

			if (!done_xlat){
				if (data->replace_len != 0 &&
				radius_xlat(replace_STR, sizeof(replace_STR), data->replace, request, NULL) == 0) {
					DEBUG2("%s: xlat on replace string failed.", data->name);
					return ret;
				}
				replace_len = (data->replace_len != 0) ? strlen(replace_STR) : 0;
				done_xlat = 1;
			}

			counter += replace_len;
			if (counter >= MAX_STRING_LEN) {
				regfree(&preg);
				DEBUG2("%s: Replacement out of limits for attribute %s with value '%s'", data->name,
						data->attribute, attr_vp->vp_strvalue);
				return ret;
			}
			if (replace_len){
				memcpy(ptr, replace_STR, replace_len);
				ptr += replace_len;
				*ptr = '\0';
			}
		}
		regfree(&preg);
		len = strlen(ptr2) + 1;		/* We add the ending NULL */
		counter += len;
		if (counter >= MAX_STRING_LEN){
			DEBUG2("%s: Replacement out of limits for attribute %s with value '%s'", data->name,
					data->attribute, attr_vp->vp_strvalue);
			return ret;
		}
		memcpy(ptr, ptr2, len);
		ptr[len] = '\0';

		DEBUG2("%s: Changed value for attribute %s from '%s' to '%s'", data->name,
				data->attribute, attr_vp->vp_strvalue, new_str);
		if (pairparsevalue(attr_vp, new_str) == NULL) {
			DEBUG2("%s: Could not write value '%s' into attribute %s: %s", data->name, new_str, data->attribute, fr_strerror());
			return ret;
		}

to_do_again:
		ret = RLM_MODULE_OK;

		if (tmp != NULL){
			tmp = attr_vp->next;
			if (tmp != NULL)
				goto do_again;
		}
	}

	return ret;
}
Example #12
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;
	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;
	}

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

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

	if (vpt.da) {
		vp = pairfindnext(&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 *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;
			data = talloc_array(request, uint8_t , vp->length);
			len = rad_vp2data(vp, data, vp->length);
			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(data);
			pairbasicfree(vpc);
			type++;
		}
		next_vp:

		talloc_free(dac);

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

	*out = '\0';
	return 0;
}
Example #13
0
/*
 *	*presult is "did comparison match or not"
 */
static int radius_do_cmp(REQUEST *request, int *presult,
			 FR_TOKEN lt, const char *pleft, FR_TOKEN token,
			 UNUSED FR_TOKEN rt, const char *pright,
#ifdef HAVE_REGEX_H
			 int cflags,
#else
			 UNUSED int cflags,
#endif
			 int modreturn)
{
	int result;
	uint32_t lint, rint;
	VALUE_PAIR *vp = NULL;
#ifdef HAVE_REGEX_H
	char buffer[8192];
#endif

	if (lt == T_BARE_WORD) {
		/*
		 *	Maybe check the last return code.
		 */
		if (token == T_OP_CMP_TRUE) {
			int isreturn;

			/*
			 *	Looks like a return code, treat is as such.
			 */
			isreturn = fr_str2int(modreturn_table, pleft, -1);
			if (isreturn != -1) {
				*presult = (modreturn == isreturn);
				return TRUE;
			}
		}

		/*
		 *	Bare words on the left can be attribute names.
		 */
		if (!(radius_get_vp(request, pleft, &vp) < 0)) {
			VALUE_PAIR *myvp;

			/*
			 *	VP exists, and that's all we're looking for.
			 */
			if (token == T_OP_CMP_TRUE) {
				*presult = (vp != NULL);
				return TRUE;
			}

			if (!vp) {
				const DICT_ATTR *da;
				
				/*
				 *	The attribute on the LHS may
				 *	have been a dynamically
				 *	registered callback.  i.e. it
				 *	doesn't exist as a VALUE_PAIR.
				 *	If so, try looking for it.
				 */
				da = dict_attrbyname(pleft);
				if (da && (da->vendor == 0) && radius_find_compare(da->attr)) {
					VALUE_PAIR *check;
					check = pairmake(request, NULL, pleft, pright, token);
					*presult = (radius_callback_compare(request, NULL, check, NULL, NULL) == 0);
					RDEBUG3("  Callback returns %d",
						*presult);
					pairfree(&check);
					return TRUE;
				}
				
				RDEBUG2("    (Attribute %s was not found)",
				       pleft);
				*presult = 0;
				return TRUE;
			}

#ifdef HAVE_REGEX_H
			/*
			 * 	Regex comparisons treat everything as
			 *	strings.
			 */
			if ((token == T_OP_REG_EQ) ||
			    (token == T_OP_REG_NE)) {
				vp_prints_value(buffer, sizeof(buffer), vp, 0);
				pleft = buffer;
				goto do_checks;
			}
#endif

			myvp = paircopyvp(request, vp);
			if (!pairparsevalue(myvp, pright)) {
				pairbasicfree(myvp);
				RDEBUG2("Failed parsing \"%s\": %s",
				       pright, fr_strerror());
				return FALSE;
			}

			myvp->op = token;
			*presult = paircmp(myvp, vp);
			pairbasicfree(myvp);
			RDEBUG3("  paircmp -> %d", *presult);
			return TRUE;
		} /* else it's not a VP in a list */
	}

#ifdef HAVE_REGEX_H
	do_checks:
#endif
	switch (token) {
	case T_OP_GE:
	case T_OP_GT:
	case T_OP_LE:
	case T_OP_LT:
		if (!all_digits(pright)) {
			RDEBUG2("    (Right field is not a number at: %s)", pright);
			return FALSE;
		}
		rint = strtoul(pright, NULL, 0);
		if (!all_digits(pleft)) {
			RDEBUG2("    (Left field is not a number at: %s)", pleft);
			return FALSE;
		}
		lint = strtoul(pleft, NULL, 0);
		break;
		
	default:
		lint = rint = 0;  /* quiet the compiler */
		break;
	}
	
	switch (token) {
	case T_OP_CMP_TRUE:
		/*
		 *	Check for truth or falsehood.
		 */
		if (all_digits(pleft)) {
			lint = strtoul(pleft, NULL, 0);
			result = (lint != 0);
			
		} else {
			result = (*pleft != '\0');
		}
		break;
		

	case T_OP_CMP_EQ:
		result = (strcmp(pleft, pright) == 0);
		break;
		
	case T_OP_NE:
		result = (strcmp(pleft, pright) != 0);
		break;
		
	case T_OP_GE:
		result = (lint >= rint);
		break;
		
	case T_OP_GT:
		result = (lint > rint);
		break;
		
	case T_OP_LE:
		result = (lint <= rint);
		break;
		
	case T_OP_LT:
		result = (lint < rint);
		break;

#ifdef HAVE_REGEX_H
	case T_OP_REG_EQ: {
		int i, compare;
		regex_t reg;
		regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
		
		/*
		 *	Include substring matches.
		 */
		compare = regcomp(&reg, pright, cflags);
		if (compare != 0) {
			if (debug_flag) {
				char errbuf[128];

				regerror(compare, &reg, errbuf, sizeof(errbuf));
				DEBUGE("Failed compiling regular expression: %s", errbuf);
			}
			return FALSE;
		}

		compare = regexec(&reg, pleft,
				  REQUEST_MAX_REGEX + 1,
				  rxmatch, 0);
		regfree(&reg);
		
		/*
		 *	Add new %{0}, %{1}, etc.
		 */
		if (compare == 0) for (i = 0; i <= REQUEST_MAX_REGEX; i++) {
			char *r;

			free(request_data_get(request, request,
					      REQUEST_DATA_REGEX | i));

			/*
			 *	No %{i}, skip it.
			 *	We MAY have %{2} without %{1}.
			 */
			if (rxmatch[i].rm_so == -1) continue;
			
			/*
			 *	Copy substring into allocated buffer
			 */
			r = rad_malloc(rxmatch[i].rm_eo -rxmatch[i].rm_so + 1);
			memcpy(r, pleft + rxmatch[i].rm_so,
			       rxmatch[i].rm_eo - rxmatch[i].rm_so);
			r[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0';

			request_data_add(request, request,
					 REQUEST_DATA_REGEX | i,
					 r, free);
		}
		result = (compare == 0);
	}
		break;
		
	case T_OP_REG_NE: {
		int compare;
		regex_t reg;
		regmatch_t rxmatch[REQUEST_MAX_REGEX + 1];
		
		/*
		 *	Include substring matches.
		 */
		compare = regcomp(&reg, pright, cflags);
		if (compare != 0) {
			if (debug_flag) {
				char errbuf[128];

				regerror(compare, &reg, errbuf, sizeof(errbuf));
				DEBUGE("Failed compiling regular expression: %s", errbuf);
			}
			return FALSE;
		}

		compare = regexec(&reg, pleft,
				  REQUEST_MAX_REGEX + 1,
				  rxmatch, 0);
		regfree(&reg);
		
		result = (compare != 0);
	}
		break;
#endif
		
	default:
		DEBUGE("Comparison operator %s is not supported",
		      fr_token_name(token));
		result = FALSE;
		break;
	}
	
	*presult = result;
	return TRUE;
}
Example #14
0
/*************************************************************************
 *
 *	Function: sql_userparse
 *
 *	Purpose: Read entries from the database and fill VALUE_PAIR structures
 *
 *************************************************************************/
int sql_userparse(TALLOC_CTX *ctx, VALUE_PAIR **head, rlm_sql_row_t row)
{
	VALUE_PAIR *vp;
	char const *ptr, *value;
	char buf[MAX_STRING_LEN];
	char do_xlat = 0;
	FR_TOKEN token, operator = T_EOL;

	/*
	 *	Verify the 'Attribute' field
	 */
	if (!row[2] || row[2][0] == '\0') {
		ERROR("rlm_sql: The 'Attribute' field is empty or NULL, skipping the entire row");
		return -1;
	}

	/*
	 *	Verify the 'op' field
	 */
	if (row[4] != NULL && row[4][0] != '\0') {
		ptr = row[4];
		operator = gettoken(&ptr, buf, sizeof(buf));
		if ((operator < T_OP_ADD) ||
		    (operator > T_OP_CMP_EQ)) {
			ERROR("rlm_sql: Invalid operator \"%s\" for attribute %s", row[4], row[2]);
			return -1;
		}

	} else {
		/*
		 *  Complain about empty or invalid 'op' field
		 */
		operator = T_OP_CMP_EQ;
		ERROR("rlm_sql: The 'op' field for attribute '%s = %s' is NULL, or non-existent.", row[2], row[3]);
		ERROR("rlm_sql: You MUST FIX THIS if you want the configuration to behave as you expect");
	}

	/*
	 *	The 'Value' field may be empty or NULL
	 */
	value = row[3];
	/*
	 *	If we have a new-style quoted string, where the
	 *	*entire* string is quoted, do xlat's.
	 */
	if (row[3] != NULL &&
	   ((row[3][0] == '\'') || (row[3][0] == '`') || (row[3][0] == '"')) &&
	   (row[3][0] == row[3][strlen(row[3])-1])) {

		token = gettoken(&value, buf, sizeof(buf));
		switch (token) {
		/*
		 *	Take the unquoted string.
		 */
		case T_SINGLE_QUOTED_STRING:
		case T_DOUBLE_QUOTED_STRING:
			value = buf;
			break;

		/*
		 *	Mark the pair to be allocated later.
		 */
		case T_BACK_QUOTED_STRING:
			value = NULL;
			do_xlat = 1;
			break;

		/*
		 *	Keep the original string.
		 */
		default:
			value = row[3];
			break;
		}
	}

	/*
	 *	Create the pair
	 */
	vp = pairmake(ctx, NULL, row[2], NULL, operator);
	if (!vp) {
		ERROR("rlm_sql: Failed to create the pair: %s",
		       fr_strerror());
		return -1;
	}

	if (do_xlat) {
		if (pairmark_xlat(vp, value) < 0) {
			ERROR("rlm_sql: Error marking pair for xlat");

			pairbasicfree(vp);
			return -1;
		}
	} else {
		if (!pairparsevalue(vp, value)) {
			ERROR("rlm_sql: Error parsing value");

			pairbasicfree(vp);
			return -1;
		}
	}

	/*
	 *	Add the pair into the packet
	 */
	pairadd(head, vp);
	return 0;
}