⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 evaluate.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * evaluate.c	Evaluate complex conditions * * Version:	$Id: evaluate.c,v 1.42 2008/05/02 09:11:18 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 2007  The FreeRADIUS server project * Copyright 2007  Alan DeKok <aland@deployingradius.com> */#include <freeradius-devel/ident.h>RCSID("$Id: evaluate.c,v 1.42 2008/05/02 09:11:18 aland Exp $")#include <freeradius-devel/radiusd.h>#include <freeradius-devel/modules.h>#include <freeradius-devel/rad_assert.h>#include <ctype.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#endifstatic int all_digits(const char *string){	const char *p = string;	if (*p == '-') p++;	while (isdigit((int) *p)) p++;	return (*p == '\0');}#ifndef NDEBUG#ifndef DEBUG4#define DEBUG4  if (debug_flag > 4)log_debug#endif#else#define DEBUG4 if (0) log_debug#endifstatic const char *filler = "????????????????????????????????????????????????????????????????";static const char *expand_string(char *buffer, size_t sizeof_buffer,				 REQUEST *request,				 FR_TOKEN value_type, const char *value){	int result;	char *p;	switch (value_type) {	default:	case T_BARE_WORD:	case T_SINGLE_QUOTED_STRING:		return value;	case T_BACK_QUOTED_STRING:		result = radius_exec_program(value, request, 1,					     buffer, sizeof_buffer, NULL,					     NULL, 0);		if (result != 0) {			return NULL;		}		/*		 *	The result should be ASCII.		 */		for (p = buffer; *p != '\0'; p++) {			if (*p < ' ' ) {				*p = '\0';				return buffer;			}		}		return buffer;	case T_DOUBLE_QUOTED_STRING:		if (!strchr(value, '%')) return value;		radius_xlat(buffer, sizeof_buffer, value, request, NULL);		return buffer;	}	return NULL;}#ifdef HAVE_REGEX_Hstatic FR_TOKEN getregex(const char **ptr, char *buffer, size_t buflen,			 int *pcflags){	const char *p = *ptr;	char *q = buffer;	if (*p != '/') return T_OP_INVALID;	*pcflags = REG_EXTENDED;	p++;	while (*p) {		if (buflen <= 1) break;		if (*p == '/') {			p++;			/*			 *	Check for case insensitivity			 */			if (*p == 'i') {				p++;				*pcflags |= REG_ICASE;			}			break;		}		if (*p == '\\') {			int x;						switch (p[1]) {			case 'r':				*q++ = '\r';				break;			case 'n':				*q++ = '\n';				break;			case 't':				*q++ = '\t';				break;			case '"':				*q++ = '"';				break;			case '\'':				*q++ = '\'';				break;			case '`':				*q++ = '`';				break;								/*				 *	FIXME: add 'x' and 'u'				 */			default:				if ((p[1] >= '0') && (p[1] <= '9') &&				    (sscanf(p, "%3o", &x) == 1)) {					*q++ = x;					p += 2;				} else {					*q++ = p[1];				}				break;			}			p += 2;			buflen--;			continue;		}		*(q++) = *(p++);		buflen--;	}	*q = '\0';	*ptr = p;	return T_DOUBLE_QUOTED_STRING;}#endifstatic const FR_NAME_NUMBER modreturn_table[] = {	{ "reject",     RLM_MODULE_REJECT       },	{ "fail",       RLM_MODULE_FAIL         },	{ "ok",         RLM_MODULE_OK           },	{ "handled",    RLM_MODULE_HANDLED      },	{ "invalid",    RLM_MODULE_INVALID      },	{ "userlock",   RLM_MODULE_USERLOCK     },	{ "notfound",   RLM_MODULE_NOTFOUND     },	{ "noop",       RLM_MODULE_NOOP         },	{ "updated",    RLM_MODULE_UPDATED      },	{ NULL, 0 }};static int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p)			{	const char *vp_name = name;	REQUEST *myrequest = request;	DICT_ATTR *da;	VALUE_PAIR *vps = NULL;	*vp_p = NULL;	/*	 *	Allow for tunneled sessions.	 */	if (strncmp(vp_name, "outer.", 6) == 0) {		if (!myrequest->parent) return TRUE;		vp_name += 6;		myrequest = myrequest->parent;	}	if (strncmp(vp_name, "request:", 8) == 0) {		vp_name += 8;		vps = myrequest->packet->vps;	} else if (strncmp(vp_name, "reply:", 6) == 0) {		vp_name += 6;		vps = myrequest->reply->vps;	} else if (strncmp(vp_name, "proxy-request:", 14) == 0) {		vp_name += 14;		if (request->proxy) vps = myrequest->proxy->vps;	} else if (strncmp(vp_name, "proxy-reply:", 12) == 0) {		vp_name += 12;		if (request->proxy_reply) vps = myrequest->proxy_reply->vps;	} else if (strncmp(vp_name, "config:", 7) == 0) {		vp_name += 7;		vps = myrequest->config_items;	} else if (strncmp(vp_name, "control:", 8) == 0) {		vp_name += 8;		vps = myrequest->config_items;	} else {		vps = myrequest->packet->vps;	}	da = dict_attrbyname(vp_name);	if (!da) return FALSE;	/* not a dictionary name */	/*	 *	May not may not be found, but it *is* a known name.	 */	*vp_p = pairfind(vps, da->attr);	return TRUE;}/* *	*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,			 FR_TOKEN rt, const char *pright,			 int cflags, int modreturn){	int result;	int lint, rint;	VALUE_PAIR *vp = NULL;	char buffer[1024];	rt = rt;		/* -Wunused */	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)) {			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) {				DEBUG2("    (Attribute %s was not found)",				       pleft);				return FALSE;			}#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			memcpy(&myvp, vp, sizeof(myvp));			if (!pairparsevalue(&myvp, pright)) {				DEBUG2("Failed parsing \"%s\": %s",				       pright, librad_errstr);				return FALSE;			}			myvp.operator = token;			*presult = paircmp(&myvp, vp);			return TRUE;		} /* else it's not a attribute in the dictionary */	}	do_checks:	switch (token) {	case T_OP_GE:	case T_OP_GT:	case T_OP_LE:	case T_OP_LT:		if (!all_digits(pright)) {			DEBUG2("    (Right field is not a number at: %s)", pright);			return FALSE;		}		rint = atoi(pright);		if (!all_digits(pleft)) {			DEBUG2("    (Left field is not a number at: %s)", pleft);			return FALSE;		}		lint = atoi(pleft);		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 = atoi(pleft);			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.		 */		regcomp(&reg, pright, cflags);		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 buffer.			 */			memcpy(buffer, pleft + 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...			 */			r = strdup(buffer);			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.		 */		regcomp(&reg, pright, cflags);		compare = regexec(&reg, pleft,				  REQUEST_MAX_REGEX + 1,				  rxmatch, 0);		regfree(&reg);				result = (compare != 0);	}		break;#endif			default:		DEBUG4(">>> NOT IMPLEMENTED %d", token);		result = FALSE;		break;	}		*presult = result;	return TRUE;}int radius_evaluate_condition(REQUEST *request, int modreturn, int depth,			      const char **ptr, int evaluate_it, int *presult){	int found_condition = FALSE;	int result = TRUE;	int invert = FALSE;	int evaluate_next_condition = evaluate_it;	const char *p = *ptr;	const char *q, *start;	FR_TOKEN token, lt, rt;	char left[1024], right[1024], comp[4];	const char *pleft, *pright;	char  xleft[1024], xright[1024];#ifdef HAVE_REGEX_H	int cflags = 0;#endif	if (!ptr || !*ptr || (depth >= 64)) {		radlog(L_ERR, "Internal sanity check failed in evaluate condition");		return FALSE;	}	while (*p) {		while ((*p == ' ') || (*p == '\t')) p++;		if (*p == '!') {			DEBUG4(">>> INVERT");			invert = TRUE;			p++;		}		/*		 *	It's a subcondition.		 */		if (*p == '(') {			const char *end = p + 1;			/*			 *	Evaluate the condition, bailing out on			 *	parse error.			 */			DEBUG4(">>> CALLING EVALUATE %s", end);			if (!radius_evaluate_condition(request, modreturn,						       depth + 1, &end,						       evaluate_next_condition,						       &result)) {				return FALSE;			}			if (invert && evaluate_next_condition) {				DEBUG2("%.*s Converting !%s -> %s",				       depth, filler,				       (result != FALSE) ? "TRUE" : "FALSE",				       (result == FALSE) ? "TRUE" : "FALSE");				       				result = (result == FALSE);				invert = FALSE;			}			/*			 *	Start from the end of the previous			 *	condition			 */			p = end;			DEBUG4(">>> EVALUATE RETURNED ::%s::", end);						if (!((*p == ')') || (*p == '!') ||			      ((p[0] == '&') && (p[1] == '&')) ||			      ((p[0] == '|') && (p[1] == '|')))) {				radlog(L_ERR, "Parse error in condition at: %s", p);				return FALSE;			}			if (*p == ')') p++;	/* skip it */			found_condition = TRUE;						while ((*p == ' ') || (*p == '\t')) p++;			/*			 *	EOL.  It's OK.			 */			if (!*p) {				DEBUG4(">>> AT EOL");				*ptr = p;				*presult = result;				return TRUE;								/*				 *	(A && B) means "evaluate B				 *	only if A was true"				 */			} else if ((p[0] == '&') && (p[1] == '&')) {				if (result == TRUE) {					evaluate_next_condition = evaluate_it;				} else {					evaluate_next_condition = FALSE;				}				p += 2;								/*				 *	(A || B) means "evaluate B				 *	only if A was false"				 */			} else if ((p[0] == '|') && (p[1] == '|')) {				if (result == FALSE) {					evaluate_next_condition = evaluate_it;				} else {					evaluate_next_condition = FALSE;				}				p += 2;			} else if (*p == ')') {				DEBUG4(">>> CLOSING BRACE");				*ptr = p;				*presult = result;				return TRUE;			} else {				/*				 *	Parse error				 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -