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

📄 parse.c

📁 使用最广泛的radius的linux的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * parse.c		Parse a policy language * * Version:	$Id: parse.c,v 1.25 2008/03/07 10:03:35 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 2004  Alan DeKok <aland@ox.org> * Copyright 2006  The FreeRADIUS server project */#include <freeradius-devel/ident.h>RCSID("$Id: parse.c,v 1.25 2008/03/07 10:03:35 aland Exp $")#include "rlm_policy.h"#ifdef HAVE_DIRENT_H#include <dirent.h>#ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif#endif#include <freeradius-devel/modules.h>const FR_NAME_NUMBER policy_return_codes[] = {	{ "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, RLM_MODULE_NUMCODES }};/* *	Explanations of what the lexical tokens are. */static const FR_NAME_NUMBER policy_explanations[] = {	{ "invalid input", POLICY_LEX_BAD },	{ "end of file", POLICY_LEX_EOF },	{ "end of line", POLICY_LEX_EOL },	{ "whitespace", POLICY_LEX_WHITESPACE },	{ "hash mark", POLICY_LEX_HASH },	{ "left bracket", POLICY_LEX_L_BRACKET },	{ "right bracket", POLICY_LEX_R_BRACKET },	{ "{", POLICY_LEX_LC_BRACKET },	{ "}", POLICY_LEX_RC_BRACKET },	{ "comma", POLICY_LEX_COMMA },	{ "logical AND", POLICY_LEX_L_AND },	{ "logical OR", POLICY_LEX_L_OR },	{ "AND", POLICY_LEX_AND },	{ "OR", POLICY_LEX_OR },	{ "logical NOT", POLICY_LEX_L_NOT },	{ "assignment", POLICY_LEX_ASSIGN },	{ "comparison", POLICY_LEX_CMP_EQUALS },	{ "comparison", POLICY_LEX_CMP_NOT_EQUALS },	{ "comparison", POLICY_LEX_LT },	{ "comparison", POLICY_LEX_GT },	{ "comparison", POLICY_LEX_LE },	{ "comparison", POLICY_LEX_GT },	{ "comparison", POLICY_LEX_RX_EQUALS },	{ "comparison", POLICY_LEX_RX_NOT_EQUALS },	{ "double quoted string", POLICY_LEX_DOUBLE_QUOTED_STRING },	{ "single quoted string", POLICY_LEX_SINGLE_QUOTED_STRING },	{ "back quoted string", POLICY_LEX_BACK_QUOTED_STRING },	{ "bare word", POLICY_LEX_BARE_WORD },	{ NULL, -1 }};const FR_NAME_NUMBER rlm_policy_tokens[] = {	{ "EOF", POLICY_LEX_EOF },	{ "#", POLICY_LEX_HASH },	{ "(", POLICY_LEX_L_BRACKET },	{ ")", POLICY_LEX_R_BRACKET },	{ "{", POLICY_LEX_LC_BRACKET },	{ "}", POLICY_LEX_RC_BRACKET },	{ ",", POLICY_LEX_COMMA },	{ "&&", POLICY_LEX_L_AND },	{ "||", POLICY_LEX_L_OR },	{ "&", POLICY_LEX_AND },	{ "|", POLICY_LEX_OR },	{ "!", POLICY_LEX_L_NOT },	{ "=", POLICY_LEX_ASSIGN },	{ "==", POLICY_LEX_CMP_EQUALS },	{ "!=", POLICY_LEX_CMP_NOT_EQUALS },	{ "=*", POLICY_LEX_CMP_TRUE },	{ "!*", POLICY_LEX_CMP_FALSE },	{ "<", POLICY_LEX_LT },	{ ">", POLICY_LEX_GT },	{ "<=", POLICY_LEX_LE },	{ ">=", POLICY_LEX_GT },	{ "=~", POLICY_LEX_RX_EQUALS },	{ "!~", POLICY_LEX_RX_NOT_EQUALS },	{ "^=", POLICY_LEX_BEFORE_HEAD_ASSIGN },	{ "^==", POLICY_LEX_BEFORE_WHERE_ASSIGN },	{ "^.", POLICY_LEX_BEFORE_HEAD_EQUALS },	{ "^.=", POLICY_LEX_BEFORE_WHERE_EQUALS },	{ "$=", POLICY_LEX_AFTER_TAIL_ASSIGN },	{ "$==", POLICY_LEX_AFTER_WHERE_ASSIGN },	{ "$.", POLICY_LEX_AFTER_TAIL_EQUALS },	{ "$.=", POLICY_LEX_AFTER_WHERE_EQUALS },	{ ".=", POLICY_LEX_CONCAT_EQUALS },	{ ":=", POLICY_LEX_SET_EQUALS },	{ "double quoted string", POLICY_LEX_DOUBLE_QUOTED_STRING },	{ "single quoted string", POLICY_LEX_SINGLE_QUOTED_STRING },	{ "back quoted string", POLICY_LEX_BACK_QUOTED_STRING },	{ "bare word", POLICY_LEX_BARE_WORD },	{ NULL, -1 }};/* *	Hand-coded lexical analysis of a string. *	Handed input string, updates token, possible a decoded *	string in buffer, and returns the pointer to the next token. * *	Lexical tokens cannot cross a string boundary. */static const char *policy_lex_string(const char *input,				     policy_lex_t *token,				     char *buffer, size_t buflen){	rad_assert(input != NULL);	if (buffer) *buffer = '\0';	switch (*input) {	case '\0':		*token = POLICY_LEX_EOL;		return NULL;	/* nothing more to do */	case ' ':	case '\t':	case '\r':	case '\n':		/*		 *	Skip over all of the whitespace in one swell foop.		 */		*token = POLICY_LEX_WHITESPACE;		while ((*input == ' ') || (*input == '\t') ||		       (*input == '\r') || (*input == '\n')) input++;		return input;	/* point to next non-whitespace character */	case '#':		/* ignore everything to the end of the line */		*token = POLICY_LEX_EOL;		return NULL;	case '(':		*token = POLICY_LEX_L_BRACKET;		return input + 1;	case ')':		*token = POLICY_LEX_R_BRACKET;		return input + 1;	case '{':		*token = POLICY_LEX_LC_BRACKET;		return input + 1;	case '}':		*token = POLICY_LEX_RC_BRACKET;		return input + 1;	case ',':		*token = POLICY_LEX_COMMA;		return input + 1;	case '+':		switch (input[1]) {		case '=':			*token = POLICY_LEX_PLUS_EQUALS;			input++;			break;		default:			*token = POLICY_LEX_PLUS;			break;		}		return input + 1;	case '-':		switch (input[1]) {		case '=':			*token = POLICY_LEX_MINUS_EQUALS;			input++;			break;		default:			*token = POLICY_LEX_MINUS;			break;		}		return input + 1;	case '.':		if (input[1] == '=') {			*token = POLICY_LEX_CONCAT_EQUALS;			return input + 2;		}		*token = POLICY_LEX_BAD;		return input + 1;		case '^':		if (input[1] == '.' ) {			if (input[2] == '=') {				*token = POLICY_LEX_BEFORE_WHERE_EQUALS;				return input + 3;			}			else {				*token = POLICY_LEX_BEFORE_HEAD_EQUALS;				return input + 2;			}		}		else if (input[1] == '=') {			if (input[2] == '=') {				*token = POLICY_LEX_BEFORE_WHERE_ASSIGN;				return input + 3;			}			else {				*token = POLICY_LEX_BEFORE_HEAD_ASSIGN;				return input + 2;			}		}					*token = POLICY_LEX_BAD;		return input + 1;	case '$':		if (input[1] == '.' ) {			if (input[2] == '=') {				*token = POLICY_LEX_AFTER_WHERE_EQUALS;				return input + 3;			}			else {				*token = POLICY_LEX_AFTER_TAIL_EQUALS;				return input + 2;			}		}		else if (input[1] == '=') {			if (input[2] == '=') {				*token = POLICY_LEX_AFTER_WHERE_ASSIGN;				return input + 3;			}			else {				*token = POLICY_LEX_AFTER_TAIL_ASSIGN;				return input + 2;			}		}		*token = POLICY_LEX_BAD;		return input + 1;	case ':':		if (input[1] == '=') {			*token = POLICY_LEX_SET_EQUALS;			return input + 2;		}		*token = POLICY_LEX_BAD;		return input + 1;	case '&':		switch (input[1]) {		case '&':			*token = POLICY_LEX_L_AND;			input++;			break;		case '=':			*token = POLICY_LEX_AND_EQUALS;			input++;			break;		default:			*token = POLICY_LEX_AND;		}		return input + 1;	case '|':		switch (input[1]) {		case '|':			*token = POLICY_LEX_L_OR;			input++;			break;		case '=':			*token = POLICY_LEX_OR_EQUALS;			input++;			break;		default:			*token = POLICY_LEX_OR;		}		return input + 1;	case '!':		switch (input[1]) {		case '=':			input++;			*token = POLICY_LEX_CMP_NOT_EQUALS;			break;		case '~':			input++;			*token = POLICY_LEX_RX_NOT_EQUALS;			break;		case '*':			input++;			*token = POLICY_LEX_CMP_FALSE;			break;		default:			*token = POLICY_LEX_L_NOT;		}		return input + 1;	case '=':		switch (input[1]) {		case '=':			input++;			*token = POLICY_LEX_CMP_EQUALS;			break;		case '~':			input++;			*token = POLICY_LEX_RX_EQUALS;			break;		case '*':			input++;			*token = POLICY_LEX_CMP_TRUE;			break;		default:			*token = POLICY_LEX_ASSIGN;		}		return input + 1;	case '<':		if (input[1] == '=') {			input++;			*token = POLICY_LEX_LE;		} else {			*token = POLICY_LEX_LT;		}		return input + 1;	case '>':		if (input[1] == '=') {			input++;			*token = POLICY_LEX_GE;		} else {			*token = POLICY_LEX_GT;		}		return input + 1;	case '"':		if (buflen < 2) {			*token = POLICY_LEX_BAD;			return input + 1;		}		input++;		while (*input != '"') {			/*			 *	Strings can't pass EOL.			 */			if (!*input) {				return POLICY_LEX_BAD;			}			/*			 *	FIXME: Embedded quotes?			 */			*(buffer++) = *(input++);			buflen--;			/*			 *	FIXME: Print more warnings?			 */			if (buflen == 1) {				break;			}		}		*buffer = '\0';		*token = POLICY_LEX_DOUBLE_QUOTED_STRING;		return input + 1; /* skip trailing '"' */	default:		/* bare word */		break;	}	/*	 *	It's a bare word, with nowhere to put it.  Die.	 */	if (!buffer) {		*token = POLICY_LEX_BAD;		return input + 1;	}	/*	 *	Getting one character is stupid.	 */	if (buflen < 2) {		*token = POLICY_LEX_BAD;		return input + 1;	}	/*	 *	Bare words are [-a-zA-Z0-9.]+	 */	while (*input) {		if (!(((*input >= '0') && (*input <= '9')) ||		      ((*input >= 'a') && (*input <= 'z')) ||		      ((*input >= 'A') && (*input <= 'Z')) ||		      (*input == '-') || (*input == '.') ||		      (*input == ':') || (*input == '_'))) {			break;		}		*(buffer++) = *(input++);		buflen--;		/*		 *	FIXME: Print more warnings?		 */		if (buflen == 1) {			break;		}	}	*buffer = '\0';	*token = POLICY_LEX_BARE_WORD;	return input;}/* *	We want to lexically analyze a file, so we need a wrapper *	around the lexical analysis of strings. */typedef struct policy_lex_file_t {	FILE		*fp;	const char	*parse;	const char	*filename;	int		lineno;	int		debug;	rbtree_t	*policies;	policy_lex_t	token;	char		buffer[1024];} policy_lex_file_t;#define POLICY_LEX_FLAG_RETURN_EOL  (1 << 0)#define POLICY_LEX_FLAG_PEEK        (1 << 1)#define POLICY_LEX_FLAG_PRINT_TOKEN (1 << 2)#define debug_tokens if ((lexer->debug & POLICY_DEBUG_PRINT_TOKENS) && fr_log_fp) fr_printf_log/* *	Function to return a token saying what it read, and possibly *	a buffer of the quoted string or bare word. */static policy_lex_t policy_lex_file(policy_lex_file_t *lexer,				    int flags,				    char *mystring, size_t mystringlen){	policy_lex_t token = POLICY_LEX_BARE_WORD; /* to prime it */	if (lexer->debug & POLICY_DEBUG_PRINT_TOKENS) {		flags |= POLICY_LEX_FLAG_PRINT_TOKEN;	}	if (!lexer->fp) {		return POLICY_LEX_EOF;	}	/*	 *	Starting off, the buffer needs to be primed.	 */	if (!lexer->parse) {		lexer->parse = fgets(lexer->buffer,				     sizeof(lexer->buffer),				     lexer->fp);		if (!lexer->parse) {			return POLICY_LEX_EOF;		}		lexer->lineno = 1;	} /* buffer is primed, read stuff */	if (lexer->token != POLICY_LEX_BAD) {		token = lexer->token;		lexer->token = POLICY_LEX_BAD;		return token;	}	/*	 *	Ignore whitespace, and keep filling the buffer	 */	while (lexer->parse) {		const char *next;		next = policy_lex_string(lexer->parse, &token,					 mystring, mystringlen);		switch (token) {		case POLICY_LEX_WHITESPACE: /* skip whitespace */			lexer->parse = next;			continue;		case POLICY_LEX_EOL: /* read another line */			lexer->parse = fgets(lexer->buffer,					     sizeof(lexer->buffer),					     lexer->fp);			lexer->lineno++;			if (flags & POLICY_LEX_FLAG_RETURN_EOL) {				return POLICY_LEX_EOL;			}			break;	/* read another token */		default:	/* return the token */			if (!(flags & POLICY_LEX_FLAG_PEEK)) {				lexer->parse = next;			}			if (flags & POLICY_LEX_FLAG_PRINT_TOKEN) {				debug_tokens("[%s token %s] ",					     (flags & POLICY_LEX_FLAG_PEEK) ? "peek " : "",					     fr_int2str(rlm_policy_tokens,							  token, "?"));			}			return token;			break;		}	} /* loop until EOF */	/*	 *	Close it for the user.	 */	fclose(lexer->fp);	lexer->fp = NULL;	return POLICY_LEX_EOF;}/* *	Push a token back onto the input. * *	FIXME: Push words, too?

⌨️ 快捷键说明

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