Thanks Chris!
Your patch cleared things up. It's up and filtering now.
It was indeed very simple (well, you have to know what to look for ;-).
Chris
On Mon, 2003-08-11 at 14:57, Chris Brotsos wrote:
> At 11:03 AM 8/9/2003, you wrote:
> >Hi Chris,
> >
> >I'm having problems finding your mail in the mailinglist history. It
> >could be too warm here to think about a good keyword to search for...
> >Can you post it again please?
>
> Hello Chris,
>
> It is attached as a file to this response. Please ignore the stuff about
> memset(). I had this version of attr_filter for awhile, and Alan advised me
> that the memset function was added to the instantiate function in a later
> release. So if you have the "memset(inst, 0, sizeof(*inst));" line in your
> instantiate function...that's a good thing :o)
>
> Thanks,
>
> Chris Brotsos
> ----
>
> ? cvsdiff.txt
> Index: rlm_attr_filter.c
> ===================================================================
> RCS file: /source/radiusd/src/modules/rlm_attr_filter/rlm_attr_filter.c,v
> retrieving revision 1.13
> diff -u -r1.13 rlm_attr_filter.c
> --- rlm_attr_filter.c 7 Jul 2003 19:04:05 -0000 1.13
> +++ rlm_attr_filter.c 11 Aug 2003 12:58:08 -0000
> @@ -3,7 +3,7 @@
> * before sending reply to the NAS/Server that sent
> * it to us.
> *
> - * Version: $Id: rlm_attr_filter.c,v 1.13 2003/07/07 19:04:05 aland Exp $
> + * Version: $Id: rlm_attr_filter.c,v 1.12 2002/08/24 16:54:56 aland Exp $
> *
> * This program is is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License, version 2 if the
> @@ -41,7 +41,7 @@
> #include "radiusd.h"
> #include "modules.h"
>
> -static const char rcsid[] = "$Id: rlm_attr_filter.c,v 1.13 2003/07/07 19:04:05
> aland Exp $";
> +static const char rcsid[] = "$Id: rlm_attr_filter.c,v 1.12 2002/08/24 16:54:56
> aland Exp $";
>
> struct attr_filter_instance {
>
> @@ -152,10 +152,6 @@
> int rcode;
>
> inst = rad_malloc(sizeof *inst);
> - if (!inst) {
> - return -1;
> - }
> - memset(inst, 0, sizeof(*inst));
>
> if (cf_section_parse(conf, inst, module_config) < 0) {
> free(inst);
> @@ -407,6 +403,238 @@
> }
>
> /*
> + * Find the named realm in the database. Create the
> + * set of attribute-value pairs to check and reply with
> + * for this realm from the database.
> + */
> +static int attr_filter_postproxy(void *instance, REQUEST *request)
> +{
> + struct attr_filter_instance *inst = instance;
> + VALUE_PAIR *request_pairs;
> + VALUE_PAIR **reply_items;
> + VALUE_PAIR *reply_item;
> + VALUE_PAIR *reply_tmp = NULL;
> + VALUE_PAIR *check_item;
> + PAIR_LIST *pl;
> + int found = 0;
> + int compare;
> + int pass, fail;
> +#ifdef HAVE_REGEX_H
> + regex_t reg;
> +#endif
> + VALUE_PAIR *realmpair;
> + REALM *realm;
> + char *realmname;
> +
> + /*
> + * It's not a proxy reply, so return NOOP
> + */
> +
> + if( request->proxy == NULL ) {
> + return( RLM_MODULE_NOOP );
> + }
> +
> + request_pairs = request->packet->vps;
> + reply_items = &request->proxy_reply->vps;
> +
> + /*
> + * Get the realm. Can't use request->config_items as
> + * that gets freed by rad_authenticate.... use the one
> + * set in the original request vps
> + */
> + realmpair = pairfind(request_pairs, PW_REALM);
> + if(!realmpair) {
> + /* Can't find a realm, so no filtering of attributes
> + * or should we use a DEFAULT entry?
> + * For now, just return NOTFOUND. (maybe NOOP?)
> + */
> + return RLM_MODULE_NOTFOUND;
> + }
> +
> + realmname = (char *) realmpair->strvalue;
> + realm = realm_find(realmname, FALSE);
> +
> + /*
> + * Find the attr_filter profile entry for the realm.
> + */
> + for(pl = inst->attrs; pl; pl = pl->next) {
> +
> + /*
> + * If the current entry is NOT a default,
> + * AND the realm does NOT match the current entry,
> + * then skip to the next entry.
> + */
> + if ( (strcmp(pl->name, "DEFAULT") != 0)
> + && (strcmp(realmname, pl->name) != 0) ) {
> + continue;
> + }
> +
> + DEBUG2(" attr_filter: Matched entry %s at line %d", pl->name,
> pl->lineno);
> +
> + found = 1;
> +
> + check_item = pl->check;
> +
> + while( check_item != NULL ) {
> +
> + /*
> + * If it is a SET operator, add the attribute to
> + * the reply list without checking reply_items.
> + *
> + */
> +
> + if( check_item->operator == T_OP_SET ) {
> + mypairappend(check_item, &reply_tmp);
> + }
> + check_item = check_item->next;
> +
> + } /* while( check_item != NULL ) */
> +
> + /*
> + * Iterate through the reply items, comparing each reply item to every
> rule,
> + * then moving it to the reply_tmp list only if it matches all rules
> for that
> + * attribute. IE, Idle-Timeout is moved only if it matches all rules
> that
> + * describe an Idle-Timeout.
> + */
> +
> + for( reply_item = *reply_items;
> + reply_item != NULL;
> + reply_item = reply_item->next ) {
> +
> + /* reset the pass,fail vars for each reply item */
> + pass = fail = 0;
> +
> + /* reset the check_item pointer to the beginning of the list */
> + check_item = pl->check;
> +
> + while( check_item != NULL ) {
> +
> + if(reply_item->attribute == check_item->attribute) {
> +
> + compare = simplepaircmp(request, reply_item, check_item);
> +
> + switch(check_item->operator) {
> +
> + case T_OP_SET: /* nothing to do for set */
> + break;
> + case T_OP_EQ:
> + default:
> + radlog(L_ERR, "Invalid operator for item %s: "
> + "reverting to '=='", check_item->name);
> +
> + case T_OP_CMP_TRUE: /* compare always == 0 */
> + case T_OP_CMP_FALSE: /* compare always == 1 */
> + case T_OP_CMP_EQ:
> + if (compare == 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +
> + case T_OP_NE:
> + if (compare != 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +
> + case T_OP_LT:
> + if (compare < 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +
> + case T_OP_GT:
> + if (compare > 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +
> + case T_OP_LE:
> + if (compare <= 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +
> + case T_OP_GE:
> + if (compare >= 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +#ifdef HAVE_REGEX_H
> + case T_OP_REG_EQ:
> + regcomp(®, (char *)check_item->strvalue, 0);
> + compare = regexec(®, (char *)reply_item->strvalue,
> + 0, NULL, 0);
> + regfree(®);
> + if (compare == 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +
> + case T_OP_REG_NE:
> + regcomp(®, (char *)check_item->strvalue, 0);
> + compare = regexec(®, (char *)reply_item->strvalue,
> + 0, NULL, 0);
> + regfree(®);
> + if (compare != 0) {
> + pass++;
> + } else {
> + fail++;
> + }
> + break;
> +#endif
> + } /* switch( check_item->operator ) */
> +
> + } /* if reply == check */
> +
> + check_item = check_item->next;
> +
> + } /* while( check ) */
> +
> + /* only move attribute if it passed all rules */
> + if (fail == 0 && pass > 0) {
> + mypairappend( reply_item, &reply_tmp);
> + }
> +
> + } /* for( reply ) */
> +
> + /* If we shouldn't fall through, break */
> + if(!fallthrough(pl->check))
> + break;
> + }
> +
> + pairfree(&request->proxy_reply->vps);
> + request->proxy_reply->vps = reply_tmp;
> +
> + /*
> + * See if we succeeded. If we didn't find the realm,
> + * then exit from the module.
> + */
> + if (!found)
> + return RLM_MODULE_OK;
> +
> + /*
> + * Remove server internal parameters.
> + */
> + pairdelete(reply_items, PW_FALL_THROUGH);
> +
> + return RLM_MODULE_UPDATED;
> +}
> +
> +/*
> * Clean up.
> */
> static int attr_filter_detach(void *instance)
> @@ -432,7 +660,7 @@
> NULL, /* accounting */
> NULL, /* checksimul */
> NULL, /* pre-proxy */
> - NULL, /* post-proxy */
> + attr_filter_postproxy, /* post-proxy */
> NULL /* post-auth */
> },
> attr_filter_detach, /* detach */
-
List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html