📄 rlm_attr_filter.c
字号:
VALUE_PAIR *send_tmp = NULL; VALUE_PAIR *check_item; PAIR_LIST *pl; int found = 0; int compare; int pass, fail; VALUE_PAIR *realmpair; REALM *realm; char *realmname; /* * Accounting is similar to pre-proxy. * Here we are concerned with what we are going to forward to * the remote server as opposed to concerns with what we will send * to the NAS based on a proxy reply to an auth request. */ if (request->packet->code != PW_ACCOUNTING_REQUEST) { return (RLM_MODULE_NOOP); } request_pairs = request->packet->vps; /* Get the realm from the original request vps. */ realmpair = pairfind(request_pairs, PW_REALM); if (!realmpair) { /* If there is no realm...NOOP */ return (RLM_MODULE_NOOP); } 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) && (strcasecmp(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 send list w/out checking. */ if (check_item->operator == T_OP_SET) { if (mypairappend(check_item, &send_tmp) < 0) { return RLM_MODULE_FAIL; } } check_item = check_item->next; } /* * Iterate through the request_pairs (items sent from NAS). * Compare each pair to every rule for this realm/DEFAULT. * Move an item to send_tmp if it matches all rules for * attribute in question. */ for (send_item = request_pairs; send_item != NULL; send_item = send_item->next ) { /* reset the pass/fail vars for each packet->vp. */ pass = fail = 0; /* reset the check_item pointer to beginning of the list */ check_item = pl->check; while (check_item != NULL) { if (send_item->attribute == check_item->attribute) { compare = simplepaircmp(request, send_item, check_item); check_pair(check_item, send_item, compare, &pass, &fail); } check_item = check_item->next; } /* only send if attribute passed all rules */ if (fail == 0 && pass > 0) { if (mypairappend (send_item, &send_tmp) < 0) { return RLM_MODULE_FAIL; } } } if (!fallthrough(pl->check)) break; } pairfree (&request->packet->vps); request->packet->vps = send_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 paramters. */ pairdelete(&send_tmp, PW_FALL_THROUGH); return RLM_MODULE_UPDATED;}static int attr_filter_preproxy (void *instance, REQUEST *request){ struct attr_filter_instance *inst = instance; VALUE_PAIR *request_pairs; VALUE_PAIR *send_item; VALUE_PAIR *send_tmp = NULL; VALUE_PAIR *check_item; PAIR_LIST *pl; int found = 0; int compare; int pass, fail; VALUE_PAIR *realmpair; REALM *realm; char *realmname; /* * Pre-proxy we are * concerned with what we are going to forward to * to the remote server as opposed to we will do with * with the remote servers' repsonse pairs. Consequently, * we deal with modifications to the request->packet->vps; */ request_pairs = request->proxy->vps; if (request->packet->code != PW_AUTHENTICATION_REQUEST) { return (RLM_MODULE_NOOP); } realmpair = pairfind(request_pairs, PW_REALM); if (!realmpair) { return (RLM_MODULE_NOOP); } realmname = (char *)realmpair->strvalue; realm = realm_find(realmname, FALSE); for (pl = inst->attrs; pl; pl = pl->next) { if ( (strcmp(pl->name, "DEFAULT") != 0) && (strcasecmp(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) { /* * Append all SET operator attributes with no check. */ if (check_item->operator == T_OP_SET) { if (mypairappend(check_item, &send_tmp) < 0) { return RLM_MODULE_FAIL; } } check_item = check_item->next; } /* * Iterate through the request_pairs (items sent from NAS). * Compare each pair to every rule for this realm/DEFAULT. * Move an item to send_tmp if it matches all rules for * attribute in question. */ for (send_item = request_pairs; send_item != NULL; send_item = send_item->next ) { /* reset the pass/fail vars for each packet->vp. */ pass = fail = 0; /* reset the check_item to the beginning */ check_item = pl->check; /* * compare each packet->vp to the entire list of * check_items for this realm. */ while (check_item != NULL) { if (send_item->attribute == check_item->attribute) { compare = simplepaircmp(request, send_item, check_item); check_pair(check_item, send_item, compare, &pass, &fail); } check_item = check_item->next; } /* only send if attribute passed all rules */ if (fail == 0 && pass > 0) { if (mypairappend (send_item, &send_tmp) < 0) { return RLM_MODULE_FAIL; } } } if (!fallthrough(pl->check)) break; } pairfree (&request->proxy->vps); request->proxy->vps = send_tmp; if (!found) return RLM_MODULE_OK; pairdelete(&send_tmp, PW_FALL_THROUGH); return RLM_MODULE_UPDATED;}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 = 0; 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 ) { if (mypairappend(check_item, &reply_tmp) < 0) { return RLM_MODULE_FAIL; } } check_item = check_item->next; } /* * 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 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); check_pair(check_item, reply_item, compare, &pass, &fail); } check_item = check_item->next; } /* only move attribute if it passed all rules */ if (fail == 0 && pass > 0) { if (mypairappend( reply_item, &reply_tmp) < 0) { return RLM_MODULE_FAIL; } } } /* 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){ struct attr_filter_instance *inst = instance; pairlist_free(&inst->attrs); free(inst->attrsfile); free(inst); return 0;}/* globally exported name */module_t rlm_attr_filter = { "attr_filter", 0, /* type: reserved */ NULL, /* initialization */ attr_filter_instantiate, /* instantiation */ { NULL, /* authentication */ attr_filter_authorize, /* authorization */ NULL, /* preaccounting */ attr_filter_accounting, /* accounting */ NULL, /* checksimul */ attr_filter_preproxy, /* pre-proxy */ attr_filter_postproxy, /* post-proxy */ NULL /* post-auth */ }, attr_filter_detach, /* detach */ NULL /* destroy */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -