📄 valuepair.c
字号:
/* * valuepair.c Valuepair functions that are radiusd-specific * and as such do not belong in the library. * * Version: $Id: valuepair.c,v 1.90 2008/03/07 09:49:49 aland Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Copyright 2000,2006 The FreeRADIUS server project * Copyright 2000 Alan DeKok <aland@ox.org> */#include <freeradius-devel/ident.h>RCSID("$Id: valuepair.c,v 1.90 2008/03/07 09:49:49 aland Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/rad_assert.h>#ifdef HAVE_REGEX_H# include <regex.h>/* * For POSIX Regular expressions. * (0) Means no extended regular expressions. * REG_EXTENDED means use extended regular expressions. */#ifndef REG_EXTENDED#define REG_EXTENDED (0)#endif#ifndef REG_NOSUB#define REG_NOSUB (0)#endif#endifstruct cmp { int attribute; int otherattr; void *instance; /* module instance */ RAD_COMPARE_FUNC compare; struct cmp *next;};static struct cmp *cmp;int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp){ int ret = -2; /* * Check for =* and !* and return appropriately */ if( check->operator == T_OP_CMP_TRUE ) return 0; if( check->operator == T_OP_CMP_FALSE ) return 1;#ifdef HAVE_REGEX_H if (check->operator == T_OP_REG_EQ) { int i, compare; regex_t reg; char name[1024]; char value[1024]; regmatch_t rxmatch[REQUEST_MAX_REGEX + 1]; snprintf(name, sizeof(name), "%%{%s}", check->name); radius_xlat(value, sizeof(value), name, request, NULL); /* * Include substring matches. */ regcomp(®, (char *)check->vp_strvalue, REG_EXTENDED); compare = regexec(®, value, REQUEST_MAX_REGEX + 1, rxmatch, 0); regfree(®); /* * Add %{0}, %{1}, etc. */ for (i = 0; i <= REQUEST_MAX_REGEX; i++) { char *p; char buffer[sizeof(check->vp_strvalue)]; /* * Didn't match: delete old * match, if it existed. */ if ((compare != 0) || (rxmatch[i].rm_so == -1)) { p = request_data_get(request, request, REQUEST_DATA_REGEX | i); if (p) { free(p); continue; } /* * No previous match * to delete, stop. */ break; } /* * Copy substring into buffer. */ memcpy(buffer, value + rxmatch[i].rm_so, rxmatch[i].rm_eo - rxmatch[i].rm_so); buffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0'; /* * Copy substring, and add it to * the request. * * Note that we don't check * for out of memory, which is * the only error we can get... */ p = strdup(buffer); request_data_add(request, request, REQUEST_DATA_REGEX | i, p, free); } if (compare == 0) return 0; return -1; } if (check->operator == T_OP_REG_NE) { int compare; regex_t reg; char name[1024]; char value[1024]; regmatch_t rxmatch[REQUEST_MAX_REGEX + 1]; snprintf(name, sizeof(name), "%%{%s}", check->name); radius_xlat(value, sizeof(value), name, request, NULL); /* * Include substring matches. */ regcomp(®, (char *)check->vp_strvalue, REG_EXTENDED); compare = regexec(®, value, REQUEST_MAX_REGEX + 1, rxmatch, 0); regfree(®); if (compare != 0) return 0; return -1; }#endif /* * Tagged attributes are equal if and only if both the * tag AND value match. */ if ((ret == 0) && check->flags.has_tag) { ret = ((int) vp->flags.tag) - ((int) check->flags.tag); if (ret != 0) return ret; } /* * Not a regular expression, compare the types. */ switch(check->type) {#ifdef ASCEND_BINARY /* * Ascend binary attributes can be treated * as opaque objects, I guess... */ case PW_TYPE_ABINARY:#endif case PW_TYPE_OCTETS: if (vp->length != check->length) { ret = 1; /* NOT equal */ break; } ret = memcmp(vp->vp_strvalue, check->vp_strvalue, vp->length); break; case PW_TYPE_STRING: ret = strcmp((char *)vp->vp_strvalue, (char *)check->vp_strvalue); break; case PW_TYPE_BYTE: case PW_TYPE_SHORT: case PW_TYPE_INTEGER: ret = vp->vp_integer - check->vp_integer; break; case PW_TYPE_DATE: ret = vp->vp_date - check->vp_date; break; case PW_TYPE_IPADDR: ret = ntohl(vp->vp_ipaddr) - ntohl(check->vp_ipaddr); break; case PW_TYPE_IPV6ADDR: ret = memcmp(&vp->vp_ipv6addr, &check->vp_ipv6addr, sizeof(vp->vp_ipv6addr)); break; case PW_TYPE_IPV6PREFIX: ret = memcmp(&vp->vp_ipv6prefix, &check->vp_ipv6prefix, sizeof(vp->vp_ipv6prefix)); break; case PW_TYPE_IFID: ret = memcmp(&vp->vp_ifid, &check->vp_ifid, sizeof(vp->vp_ifid)); break; default: break; } return ret;}/* * Compare 2 attributes. May call the attribute compare function. */int radius_callback_compare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR *check_pairs, VALUE_PAIR **reply_pairs){ struct cmp *c; /* * Check for =* and !* and return appropriately */ if( check->operator == T_OP_CMP_TRUE ) return 0; /* always return 0/EQUAL */ if( check->operator == T_OP_CMP_FALSE ) return 1; /* always return 1/NOT EQUAL */ /* * See if there is a special compare function. * * FIXME: use new RB-Tree code. */ for (c = cmp; c; c = c->next) if (c->attribute == check->attribute) { return (c->compare)(c->instance, req, request, check, check_pairs, reply_pairs); } if (!request) return -1; /* doesn't exist, don't compare it */ return radius_compare_vps(req, check, request);}/* * See what attribute we want to compare with. */static int otherattr(int attr){ struct cmp *c; for (c = cmp; c; c = c->next) { if (c->attribute == attr) return c->otherattr; } return attr;}/* * Register a function as compare function. * compare_attr is the attribute in the request we want to * compare with. Normally this is the same as "attr". * You can set this to: * * -1 the same as "attr" * 0 always call compare function, not tied to request attribute * >0 Attribute to compare with. * * For example, PW_GROUP in a check item needs to be compared * with PW_USER_NAME in the incoming request. */int paircompare_register(int attr, int compare_attr, RAD_COMPARE_FUNC fun, void *instance){ struct cmp *c; paircompare_unregister(attr, fun); c = rad_malloc(sizeof(struct cmp)); c->compare = fun; c->attribute = attr; c->otherattr = compare_attr; c->instance = instance; c->next = cmp; cmp = c; return 0;}/* * Unregister a function. */void paircompare_unregister(int attr, RAD_COMPARE_FUNC fun){ struct cmp *c, *last; last = NULL; for (c = cmp; c; c = c->next) { if (c->attribute == attr && c->compare == fun) break; last = c; } if (c == NULL) return; if (last != NULL) last->next = c->next; else cmp = c->next; free(c);}/* * Compare two pair lists except for the password information. * For every element in "check" at least one matching copy must * be present in "reply". * * Return 0 on match. */int paircompare(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check, VALUE_PAIR **reply){ VALUE_PAIR *check_item; VALUE_PAIR *auth_item; int result = 0; int compare; int other; for (check_item = check; check_item != NULL; check_item = check_item->next) { /* * If the user is setting a configuration value, * then don't bother comparing it to any attributes * sent to us by the user. It ALWAYS matches. */ if ((check_item->operator == T_OP_SET) || (check_item->operator == T_OP_ADD)) { continue; } switch (check_item->attribute) { /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -