Introduce Future Proofing to ACF parsing.
- Allow ACF files to contain sections that are unsupported - introduce a pragma disable-strict-parsing to disable strict parsing and allow files to be accepted Add tests for future proof parser functionaluty Expanded tests for Access Security configurations to validate parsing behaviors for unsupported elements. Added detailed cases covering invalid formats, unsupported modifications, and acceptable configurations while maintaining future-proofing and backward compatibility assurances. Refactor parser to handle generic items and floating-point tokens Replaced "unsupported elements" with a more flexible "generic items" mechanism to enhance parser extensibility. Added support for floating-point numbers in parsing rules. Updated tests and rules to reflect these changes, ensuring better handling of nested and unknown configurations. Add warnings for unsupported ACF elements and update tests Introduced `yywarn` to log warnings for unsupported ACF elements, rule permissions, and conditions in `asLib.y`. Updated test configuration to replace generic placeholders with more descriptive names. Adjusted test cases and reduced the test plan count to reflect the changes. Remove unused strictParsing logic and improve error handling. Removed strictParsing variable and related code as it was no longer in use. Enhanced error messaging and parsing logic for handling unsupported elements. Updated test cases for better clarity and expanded coverage of edge cases. Enhance ASLib parsing with Int64/Float64 support. Updated ASLib to utilize 64-bit integers and floats for improved parsing precision. Replaced legacy parsing methods with epics-friendly functions, improved error handling, and adjusted tests and grammar accordingly. Refactor AS parser to separate non-rule keywords Introduced a new `non_rule_keyword` type and moved `tokenASG` and `tokenRULE` under it for better logical grouping. This improves parser clarity and maintains a clean separation of keyword types. Add rule-specific parsing for generic block elements Introduce new rules for parsing rule-specific generic block elements and their names. This enhances the grammar to handle additional cases while maintaining memory management and error handling. Adjust references to use the new rule where applicable. Refactor grammar rules in asLib.y to remove remaining shift/reduce conflict Reorganize and refine grammar rules for handling generic elements, blocks, and lists. Simplifies the structure while introducing clearer distinctions between different constructs. This enhances maintainability and removes ambiguities in parsing.
This commit is contained in:
committed by
Michael Davidsaver
parent
46ecf5d25c
commit
9b532540bf
@@ -202,6 +202,7 @@ typedef struct{
|
||||
ELLLIST uagList; /*List of ASGUAG*/
|
||||
ELLLIST hagList; /*List of ASGHAG*/
|
||||
int trapMask;
|
||||
int ignore; // 1 if rule to be ignored because of unknown elements
|
||||
} ASGRULE;
|
||||
typedef struct{
|
||||
ELLNODE node;
|
||||
|
||||
@@ -12,6 +12,7 @@ static int yyerror(char *);
|
||||
static int yy_start;
|
||||
#include "asLibRoutines.c"
|
||||
static int yyFailed = FALSE;
|
||||
static int yyWarned = FALSE;
|
||||
static int line_num=1;
|
||||
static UAG *yyUag=NULL;
|
||||
static HAG *yyHag=NULL;
|
||||
@@ -21,17 +22,24 @@ static ASGRULE *yyAsgRule=NULL;
|
||||
|
||||
%start asconfig
|
||||
|
||||
%token tokenUAG tokenHAG tokenASG tokenRULE tokenCALC
|
||||
%token <Str> tokenINP
|
||||
%token <Int> tokenINTEGER
|
||||
%token <Str> tokenSTRING
|
||||
%token <Str> tokenUAG tokenHAG tokenASG tokenRULE tokenCALC tokenINP tokenSTRING
|
||||
%token <Int64> tokenINT64
|
||||
%token <Float64> tokenFLOAT64
|
||||
|
||||
%union
|
||||
{
|
||||
int Int;
|
||||
epicsInt64 Int64;
|
||||
epicsFloat64 Float64;
|
||||
char *Str;
|
||||
}
|
||||
|
||||
%type <Str> non_rule_keyword
|
||||
%type <Str> generic_block_elem_name
|
||||
%type <Str> generic_block_elem
|
||||
%type <Str> rule_generic_block_elem
|
||||
%type <Str> rule_generic_block_elem_name
|
||||
%type <Str> keyword
|
||||
|
||||
%%
|
||||
|
||||
asconfig: asconfig asconfig_item
|
||||
@@ -43,13 +51,121 @@ asconfig_item: tokenUAG uag_head uag_body
|
||||
| tokenHAG hag_head
|
||||
| tokenASG asg_head asg_body
|
||||
| tokenASG asg_head
|
||||
| generic_item
|
||||
;
|
||||
|
||||
keyword: tokenUAG
|
||||
| tokenHAG
|
||||
| tokenCALC
|
||||
| non_rule_keyword
|
||||
;
|
||||
|
||||
non_rule_keyword: tokenASG
|
||||
| tokenRULE
|
||||
| tokenINP
|
||||
;
|
||||
|
||||
generic_item: tokenSTRING generic_head generic_list_block
|
||||
{
|
||||
yywarn("Ignoring unsupported TOP LEVEL Access Control Definition", $1);
|
||||
free($1);
|
||||
}
|
||||
| tokenSTRING generic_head generic_block
|
||||
{
|
||||
yywarn("Ignoring unsupported TOP LEVEL Access Control Definition", $1);
|
||||
free($1);
|
||||
}
|
||||
| tokenSTRING generic_head
|
||||
{
|
||||
yywarn("Ignoring unsupported TOP LEVEL Access Control Definition", $1);
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
||||
generic_head: '(' ')'
|
||||
| '(' generic_element ')'
|
||||
| '(' generic_list ')'
|
||||
;
|
||||
|
||||
generic_list_block: '{' generic_element '}'
|
||||
'{' generic_list '}'
|
||||
;
|
||||
|
||||
generic_list: generic_list ',' generic_element
|
||||
| generic_element ',' generic_element
|
||||
;
|
||||
|
||||
generic_element: keyword
|
||||
| tokenSTRING
|
||||
{
|
||||
free($1);
|
||||
}
|
||||
| tokenINT64
|
||||
| tokenFLOAT64
|
||||
;
|
||||
|
||||
generic_block: '{' generic_element '}'
|
||||
| '{' generic_list '}'
|
||||
| '{' generic_block_list '}'
|
||||
;
|
||||
|
||||
generic_block_list: generic_block_list generic_block_elem
|
||||
{
|
||||
free($2);
|
||||
}
|
||||
| generic_block_elem
|
||||
{
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
||||
generic_block_elem: generic_block_elem_name generic_head generic_block
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| generic_block_elem_name generic_head
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
generic_block_elem_name: keyword
|
||||
{
|
||||
$$ = strdup($1);
|
||||
if (!$$) yyerror("Out of memory");
|
||||
}
|
||||
| tokenSTRING
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
rule_generic_block_elem: rule_generic_block_elem_name generic_head generic_block
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| rule_generic_block_elem_name generic_head
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
rule_generic_block_elem_name: non_rule_keyword
|
||||
{
|
||||
$$ = strdup($1);
|
||||
if (!$$) yyerror("Out of memory");
|
||||
}
|
||||
| tokenSTRING
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
uag_head: '(' tokenSTRING ')'
|
||||
{
|
||||
yyUag = asUagAdd($2);
|
||||
if(!yyUag) yyerror("");
|
||||
free((void *)$2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -67,7 +183,7 @@ uag_user_list_name: tokenSTRING
|
||||
{
|
||||
if (asUagAddUser(yyUag,$1))
|
||||
yyerror("");
|
||||
free((void *)$1);
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -75,7 +191,7 @@ hag_head: '(' tokenSTRING ')'
|
||||
{
|
||||
yyHag = asHagAdd($2);
|
||||
if(!yyHag) yyerror("");
|
||||
free((void *)$2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -90,7 +206,7 @@ hag_host_list_name: tokenSTRING
|
||||
{
|
||||
if (asHagAddHost(yyHag,$1))
|
||||
yyerror("");
|
||||
free((void *)$1);
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -98,7 +214,7 @@ asg_head: '(' tokenSTRING ')'
|
||||
{
|
||||
yyAsg = asAsgAdd($2);
|
||||
if(!yyAsg) yyerror("");
|
||||
free((void *)$2);
|
||||
free($2);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -114,49 +230,49 @@ asg_body_item: inp_config | rule_config
|
||||
|
||||
inp_config: tokenINP '(' tokenSTRING ')'
|
||||
{
|
||||
if (asAsgAddInp(yyAsg,$3,$<Int>1))
|
||||
if (asAsgAddInp(yyAsg,$3,(int)$<Int64>1))
|
||||
yyerror("");
|
||||
free((void *)$3);
|
||||
free($3);
|
||||
}
|
||||
;
|
||||
|
||||
rule_config: tokenRULE rule_head rule_body
|
||||
| tokenRULE rule_head
|
||||
|
||||
rule_head: rule_head_manditory rule_head_options
|
||||
rule_head: '(' rule_head_mandatory ',' rule_log_option ')'
|
||||
| '(' rule_head_mandatory ')'
|
||||
;
|
||||
|
||||
rule_head_manditory: '(' tokenINTEGER ',' tokenSTRING
|
||||
|
||||
rule_head_mandatory: tokenINT64 ',' tokenSTRING
|
||||
{
|
||||
asAccessRights rights;
|
||||
|
||||
if((strcmp($4,"NONE")==0)) {
|
||||
rights=asNOACCESS;
|
||||
} else if((strcmp($4,"READ")==0)) {
|
||||
rights=asREAD;
|
||||
} else if((strcmp($4,"WRITE")==0)) {
|
||||
rights=asWRITE;
|
||||
if ($1 < 0) {
|
||||
char message[40];
|
||||
sprintf(message, "RULE: LEVEL must be positive: %lld", $1);
|
||||
yyerror(message);
|
||||
} else if((strcmp($3,"NONE")==0)) {
|
||||
yyAsgRule = asAsgAddRule(yyAsg,asNOACCESS,(int)$1);
|
||||
} else if((strcmp($3,"READ")==0)) {
|
||||
yyAsgRule = asAsgAddRule(yyAsg,asREAD,(int)$1);
|
||||
} else if((strcmp($3,"WRITE")==0)) {
|
||||
yyAsgRule = asAsgAddRule(yyAsg,asWRITE,(int)$1);
|
||||
} else {
|
||||
yyerror("Access rights must be NONE, READ or WRITE");
|
||||
rights = asNOACCESS;
|
||||
yywarn("Ignoring RULE that contains an unsupported keyword", $3);
|
||||
}
|
||||
yyAsgRule = asAsgAddRule(yyAsg,rights,$2);
|
||||
free((void *)$4);
|
||||
free($3);
|
||||
}
|
||||
;
|
||||
|
||||
rule_head_options: ')'
|
||||
| rule_log_options
|
||||
|
||||
rule_log_options: ',' tokenSTRING ')'
|
||||
rule_log_option: tokenSTRING
|
||||
{
|
||||
if((strcmp($2,"TRAPWRITE")==0)) {
|
||||
if((strcmp($1,"TRAPWRITE")==0)) {
|
||||
long status;
|
||||
status = asAsgAddRuleOptions(yyAsgRule,AS_TRAP_WRITE);
|
||||
if(status) yyerror("");
|
||||
} else if((strcmp($2,"NOTRAPWRITE")!=0)) {
|
||||
} else if((strcmp($1,"NOTRAPWRITE")!=0)) {
|
||||
yyerror("Log options must be TRAPWRITE or NOTRAPWRITE");
|
||||
}
|
||||
free((void *)$2);
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -173,7 +289,14 @@ rule_list_item: tokenUAG '(' rule_uag_list ')'
|
||||
{
|
||||
if (asAsgRuleCalc(yyAsgRule,$3))
|
||||
yyerror("");
|
||||
free((void *)$3);
|
||||
free($3);
|
||||
}
|
||||
| rule_generic_block_elem
|
||||
{
|
||||
yywarn("Ignoring RULE that contains an unsupported keyword", $1);
|
||||
free($1);
|
||||
if (asAsgRuleDisable(yyAsgRule))
|
||||
yyerror("");
|
||||
}
|
||||
;
|
||||
|
||||
@@ -185,7 +308,7 @@ rule_uag_list_name: tokenSTRING
|
||||
{
|
||||
if (asAsgRuleUagAdd(yyAsgRule,$1))
|
||||
yyerror("");
|
||||
free((void *)$1);
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -197,7 +320,7 @@ rule_hag_list_name: tokenSTRING
|
||||
{
|
||||
if (asAsgRuleHagAdd(yyAsgRule,$1))
|
||||
yyerror("");
|
||||
free((void *)$1);
|
||||
free($1);
|
||||
}
|
||||
;
|
||||
%%
|
||||
@@ -207,12 +330,19 @@ rule_hag_list_name: tokenSTRING
|
||||
static int yyerror(char *str)
|
||||
{
|
||||
if (strlen(str))
|
||||
errlogPrintf("%s at line %d\n", str, line_num);
|
||||
fprintf(stderr, ERL_ERROR " %s at line %d\n", str, line_num);
|
||||
else
|
||||
errlogPrintf(ERL_ERROR " at line %d\n", line_num);
|
||||
fprintf(stderr, ERL_ERROR " at line %d\n", line_num);
|
||||
yyFailed = TRUE;
|
||||
return 0;
|
||||
}
|
||||
static int yywarn(char *str, char *token)
|
||||
{
|
||||
if (!yyWarned && strlen(str) && strlen(token))
|
||||
fprintf(stderr, ERL_WARNING " %s at line %d: %s\n", str, line_num, token);
|
||||
yyWarned = TRUE;
|
||||
return 0;
|
||||
}
|
||||
static int myParse(ASINPUTFUNCPTR inputfunction)
|
||||
{
|
||||
static int FirstFlag = 1;
|
||||
@@ -222,6 +352,7 @@ static int myParse(ASINPUTFUNCPTR inputfunction)
|
||||
if (!FirstFlag) {
|
||||
line_num=1;
|
||||
yyFailed = FALSE;
|
||||
yyWarned = FALSE;
|
||||
yyreset();
|
||||
yyrestart(NULL);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ static long asAsgAddRuleOptions(ASGRULE *pasgrule,int trapMask);
|
||||
static long asAsgRuleUagAdd(ASGRULE *pasgrule,const char *name);
|
||||
static long asAsgRuleHagAdd(ASGRULE *pasgrule,const char *name);
|
||||
static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc);
|
||||
static long asAsgRuleDisable(ASGRULE *pasgrule);
|
||||
|
||||
/*
|
||||
asInitialize can be called while access security is already active.
|
||||
@@ -585,8 +586,8 @@ int epicsStdCall asDumpFP(
|
||||
pasginp = (ASGINP *)ellNext(&pasginp->node);
|
||||
}
|
||||
while(pasgrule) {
|
||||
int print_end_brace;
|
||||
|
||||
int print_rule_end_brace = FALSE;
|
||||
if (pasgrule->ignore) goto next_rule;
|
||||
fprintf(fp,"\tRULE(%d,%s,%s)",
|
||||
pasgrule->level,asAccessName[pasgrule->access],
|
||||
asTrapOption[pasgrule->trapMask]);
|
||||
@@ -594,10 +595,10 @@ int epicsStdCall asDumpFP(
|
||||
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
|
||||
if(pasguag || pasghag || pasgrule->calc) {
|
||||
fprintf(fp," {\n");
|
||||
print_end_brace = TRUE;
|
||||
print_rule_end_brace = TRUE;
|
||||
} else {
|
||||
fprintf(fp,"\n");
|
||||
print_end_brace = FALSE;
|
||||
print_rule_end_brace = FALSE;
|
||||
}
|
||||
if(pasguag) fprintf(fp,"\t\tUAG(");
|
||||
while(pasguag) {
|
||||
@@ -605,7 +606,6 @@ int epicsStdCall asDumpFP(
|
||||
pasguag = (ASGUAG *)ellNext(&pasguag->node);
|
||||
if(pasguag) fprintf(fp,","); else fprintf(fp,")\n");
|
||||
}
|
||||
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
|
||||
if(pasghag) fprintf(fp,"\t\tHAG(");
|
||||
while(pasghag) {
|
||||
fprintf(fp,"%s",pasghag->phag->name);
|
||||
@@ -618,7 +618,8 @@ int epicsStdCall asDumpFP(
|
||||
fprintf(fp," result=%s",(pasgrule->result==1 ? "TRUE" : "FALSE"));
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
if(print_end_brace) fprintf(fp,"\t}\n");
|
||||
next_rule:
|
||||
if(print_rule_end_brace) fprintf(fp,"\t}\n");
|
||||
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
|
||||
}
|
||||
pasgmember = (ASGMEMBER *)ellFirst(&pasg->memberList);
|
||||
@@ -735,7 +736,7 @@ int epicsStdCall asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
pasg = (ASG *)ellFirst(&pasbase->asgList);
|
||||
if(!pasg) fprintf(fp,"No ASGs\n");
|
||||
while(pasg) {
|
||||
int print_end_brace;
|
||||
int print_end_brace = FALSE;
|
||||
|
||||
if(asgname && strcmp(asgname,pasg->name)!=0) {
|
||||
pasg = (ASG *)ellNext(&pasg->node);
|
||||
@@ -761,8 +762,8 @@ int epicsStdCall asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
pasginp = (ASGINP *)ellNext(&pasginp->node);
|
||||
}
|
||||
while(pasgrule) {
|
||||
int print_end_brace;
|
||||
|
||||
int print_rule_end_brace = FALSE;
|
||||
if ( pasgrule->ignore) goto next_rule;
|
||||
fprintf(fp,"\tRULE(%d,%s,%s)",
|
||||
pasgrule->level,asAccessName[pasgrule->access],
|
||||
asTrapOption[pasgrule->trapMask]);
|
||||
@@ -770,10 +771,10 @@ int epicsStdCall asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
pasghag = (ASGHAG *)ellFirst(&pasgrule->hagList);
|
||||
if(pasguag || pasghag || pasgrule->calc) {
|
||||
fprintf(fp," {\n");
|
||||
print_end_brace = TRUE;
|
||||
print_rule_end_brace = TRUE;
|
||||
} else {
|
||||
fprintf(fp,"\n");
|
||||
print_end_brace = FALSE;
|
||||
print_rule_end_brace = FALSE;
|
||||
}
|
||||
if(pasguag) fprintf(fp,"\t\tUAG(");
|
||||
while(pasguag) {
|
||||
@@ -793,7 +794,8 @@ int epicsStdCall asDumpRulesFP(FILE *fp,const char *asgname)
|
||||
fprintf(fp," result=%s",(pasgrule->result==1 ? "TRUE" : "FALSE"));
|
||||
fprintf(fp,"\n");
|
||||
}
|
||||
if(print_end_brace) fprintf(fp,"\t}\n");
|
||||
next_rule:
|
||||
if(print_rule_end_brace) fprintf(fp,"\t}\n");
|
||||
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
|
||||
}
|
||||
if(print_end_brace) fprintf(fp,"}\n");
|
||||
@@ -948,6 +950,7 @@ static long asComputeAsgPvt(ASG *pasg)
|
||||
if(!asActive) return(S_asLib_asNotActive);
|
||||
pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
|
||||
while(pasgrule) {
|
||||
if ( pasgrule->ignore) goto next_rule;
|
||||
double result = pasgrule->result; /* set for VAL */
|
||||
long status;
|
||||
|
||||
@@ -960,6 +963,8 @@ static long asComputeAsgPvt(ASG *pasg)
|
||||
pasgrule->result = ((result>.99) && (result<1.01)) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
next_rule:
|
||||
pasgrule = (ASGRULE *)ellNext(&pasgrule->node);
|
||||
}
|
||||
pasg->inpChanged = FALSE;
|
||||
@@ -995,6 +1000,7 @@ static long asComputePvt(ASCLIENTPVT asClientPvt)
|
||||
oldaccess=pasgclient->access;
|
||||
pasgrule = (ASGRULE *)ellFirst(&pasg->ruleList);
|
||||
while(pasgrule) {
|
||||
if (pasgrule->ignore) goto next_rule;
|
||||
if(access == asWRITE) break;
|
||||
if(access>=pasgrule->access) goto next_rule;
|
||||
if(pasgclient->level > pasgrule->level) goto next_rule;
|
||||
@@ -1408,3 +1414,14 @@ static long asAsgRuleCalc(ASGRULE *pasgrule,const char *calc)
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a rule if it contains unsupported elements
|
||||
* @param pasgrule the rule to disable
|
||||
* @return Non-zero if rule was not disabled
|
||||
*/
|
||||
static long asAsgRuleDisable(ASGRULE *pasgrule) {
|
||||
if (!pasgrule) return 1;
|
||||
pasgrule->ignore = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ punctuation [(){},]
|
||||
link [A-U]
|
||||
|
||||
%{
|
||||
#include "epicsStdlib.h"
|
||||
|
||||
static ASINPUTFUNCPTR *my_yyinput;
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(b,r,ms) (r=(*my_yyinput)((char *)b,ms))
|
||||
@@ -43,14 +45,31 @@ RULE { return(tokenRULE); }
|
||||
CALC { return(tokenCALC); }
|
||||
|
||||
INP{link} {
|
||||
yylval.Int = (unsigned char)yytext[3];
|
||||
yylval.Int -= 'A';
|
||||
yylval.Int64 = (unsigned char)yytext[3];
|
||||
yylval.Int64 -= 'A';
|
||||
return(tokenINP);
|
||||
}
|
||||
|
||||
{digit}+ { /*integer*/
|
||||
yylval.Int = atoi((char *)yytext);
|
||||
return(tokenINTEGER);
|
||||
[-+]?{digit}*\.{digit}+([eE][-+]?{digit}+)? {
|
||||
char *end;
|
||||
if (epicsParseDouble((char *)yytext, &yylval.Float64, &end) ) {
|
||||
char message[40];
|
||||
sprintf(message, "Error parsing Float64: %s", (char *)yytext);
|
||||
yyerror(message);
|
||||
} else {
|
||||
return(tokenFLOAT64);
|
||||
}
|
||||
}
|
||||
|
||||
[-+]?{digit}+ { /*integer 64*/
|
||||
char *end;
|
||||
if (epicsParseInt64((char *)yytext, &yylval.Int64, 10, &end) ) {
|
||||
char message[40];
|
||||
sprintf(message, "Error parsing Int64: %s", (char *)yytext);
|
||||
yyerror(message);
|
||||
} else {
|
||||
return(tokenINT64);
|
||||
}
|
||||
}
|
||||
|
||||
{name}+ { /*unquoted string*/
|
||||
|
||||
@@ -22,18 +22,538 @@ static char *asUser,
|
||||
*asHost;
|
||||
static int asAsl;
|
||||
|
||||
/**
|
||||
* @brief Test data with Host Access Groups (HAG)
|
||||
*
|
||||
* This includes a host access group (HAG) for localhost and a default Access Security Group (ASG)
|
||||
* with rules for read and write access to the HAG.
|
||||
*/
|
||||
static const char hostname_config[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(rw) {\n"
|
||||
" RULE(1, WRITE) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should be silently ignored, but the rest of the config is processed.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST)
|
||||
* - valid top level keyword with well-formed arg list
|
||||
*/
|
||||
static const char supported_config_1[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"GENERIC(WELL, FORMED, ARG, LIST)\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should be silently ignored, but the rest of the config is processed.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST) { WELL,FORMED,LIST }
|
||||
* - valid top level keyword with well-formed arg list and valid arg list body
|
||||
*/
|
||||
static const char supported_config_2[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"SIMPLE(WELL, FORMED, ARG, LIST) {\n"
|
||||
" WELL, FORMED, LIST\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should be silently ignored, but the rest of the config is processed.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST) { recursive-body-keyword(WELL,FORMED,LIST) }
|
||||
* - valid top level keyword with well-formed arg list and valid recursive body
|
||||
* - includes quoted strings, integers, and floating point numbers
|
||||
*/
|
||||
static const char supported_config_3[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"COMPLEX_ARGUMENTS(1, WELL, \"FORMED\", ARG, LIST) {\n"
|
||||
" ALSO_GENERIC(WELL, FORMED, ARG, LIST, 2.0) \n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should be silently ignored, but the rest of the config is processed.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST) { recursive-body-keyword(WELL,FORMED,LIST) { AND_BODY } }
|
||||
* - valid top level keyword with well-formed arg list and valid recursive body, with a nested body
|
||||
* - includes floating point numbers, and an empty arg list
|
||||
*/
|
||||
static const char supported_config_4[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"SUB_BLOCKS(1.0, ARGS) {\n"
|
||||
" ALSO_GENERIC() {\n"
|
||||
" AND_LIST_BODY\n"
|
||||
" }\n"
|
||||
" ANOTHER_GENERIC() {\n"
|
||||
" BIGGER, LIST, BODY\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should be silently ignored, but the rest of the config is processed.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST) { recursive-body-keyword(WELL,FORMED,LIST) { AND_RECURSIVE_BODY() {LIST, LIST } }
|
||||
* - valid top level keyword with well-formed arg list and valid recursive body, with a nested recursion
|
||||
* - includes floating point numbers, and an empty arg list
|
||||
*/
|
||||
static const char supported_config_5[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"RECURSIVE_SUB_BLOCKS(1.0, -2.3, +4.5, ARGS, +2.71828E-23, -2.71828e+23, +12, -13, +-14) {\n"
|
||||
" ALSO_GENERIC() {\n"
|
||||
" AND_RECURSIVE(FOO) {\n"
|
||||
" LIST, BODY\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(+1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should be silently ignored, but the rest of the config is processed.
|
||||
*
|
||||
* top-unknown-keyword(KEYWORD) { KEYWORD(KEYWORD) }
|
||||
* - valid top level keyword with keyword for args, recursive body name, and arg list
|
||||
* - top level generic items referenced in RULES, then RULES are ignored
|
||||
*/
|
||||
static const char supported_config_6[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"WITH_KEYWORDS(UAG) {\n"
|
||||
" ASG(HAL, IMP, CALC, RULE)\n"
|
||||
" HAL(USG, MAL) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ignored) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" WITH_KEYWORDS(UAG)\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
" RULE(2, WRITE) {\n"
|
||||
" WITH_KEYWORDS(UAG)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported elements should be silently ignored, and the rule will not match,
|
||||
* but the rest of the config is processed.
|
||||
*
|
||||
* - RULE contains unsupported elements
|
||||
*/
|
||||
static const char supported_config_7[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" BAD_PREDICATE(\"x509\")\n"
|
||||
" BAD_PREDICATE_AS_WELL(\"EPICS Certificate Authority\")\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported elements should be silently ignored, and the rule will not match,
|
||||
* but the rest of the config is processed.
|
||||
*
|
||||
* - unexpected permission name in arg list for RULE element ignored
|
||||
*/
|
||||
static const char supported_config_8[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, ADDITIONAL_PERMISSION) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
;
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should cause an error as the format is invalid.
|
||||
*
|
||||
* top-unknown-keyword( a b )
|
||||
* - invalid arg list missing commas
|
||||
*/
|
||||
static const char unsupported_config_1[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"GENERIC(not well-formed arg list)\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should cause an error as the format is invalid.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST) { a b }
|
||||
* - invalid string list
|
||||
*/
|
||||
static const char unsupported_config_2[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"GENERIC(WELL, FORMED, ARG, LIST) {\n"
|
||||
" NOT WELL-FORMED BODY\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should cause an error as the format is invalid.
|
||||
*
|
||||
* top-unknown-keyword { a, b }
|
||||
* - missing parameters (must have at least an empty arg list)
|
||||
*/
|
||||
static const char unsupported_config_3[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"GENERIC {\n"
|
||||
" WELL, FORMED, LIST, BODY\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should cause an error as the format is invalid.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST) { X, Y(a b c) }
|
||||
* - bad arg list for recursive body
|
||||
*/
|
||||
static const char unsupported_config_4[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"GENERIC(WELL, FORMED, ARG, LIST) {\n"
|
||||
" BODY(BAD ARG LIST)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Test data with unsupported elements.
|
||||
* The unsupported element should cause an error as the format is invalid.
|
||||
*
|
||||
* top-unknown-keyword(WELL,FORMED,LIST) { X, Y(a b c) }
|
||||
* - mix of list and recursive type bodies
|
||||
*/
|
||||
static const char unsupported_config_5[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"GENERIC(WELL, FORMED, ARG, LIST) {\n"
|
||||
" LIST, BODY, MIXED, WITH,\n"
|
||||
" RECURSIVE_BODY(ARG, LIST)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* The modification to a well known element should cause an error.
|
||||
*
|
||||
* - bad arg list for ASG element
|
||||
*/
|
||||
static const char unsupported_mod_1[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro BAD ARG LIST) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* The modification to a well known element should cause an error.
|
||||
*
|
||||
* - bad arg list for HAG element
|
||||
*/
|
||||
static const char unsupported_mod_2[] = ""
|
||||
"HAG(BAD ARG LIST) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* The modification to a well known element should cause an error.
|
||||
*
|
||||
* - bad arg list for RULE element
|
||||
*/
|
||||
static const char unsupported_mod_3[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0 BAD ARG LIST)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* The modification to a well known element should cause an error.
|
||||
*
|
||||
* - bad arg count for ASG element
|
||||
*/
|
||||
static const char unsupported_mod_4[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro, UNKNOWN_PERMISSION) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* The modification to a well known element should cause an error.
|
||||
*
|
||||
* - unexpected name in arg list for RULE element
|
||||
*/
|
||||
static const char unsupported_mod_5[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE, UNKNOWN_FLAG)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* The modification to a well known element should cause an error.
|
||||
*
|
||||
* - unexpected recursive body mixed in with HAG string list body
|
||||
*/
|
||||
static const char unsupported_mod_6[] = ""
|
||||
"HAG(foo) {\n"
|
||||
" localhost,\n"
|
||||
" NETWORK(\"127.0.0.1\")\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* The modification to a well known element should cause an error.
|
||||
*
|
||||
* - unexpected recursive body mixed in with UAG string list body
|
||||
*/
|
||||
static const char unsupported_mod_7[] = ""
|
||||
"UAG(foo) {\n"
|
||||
" alice,\n"
|
||||
" GROUP(admin)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(DEFAULT) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
"}\n"
|
||||
|
||||
"ASG(ro) {\n"
|
||||
" RULE(0, NONE)\n"
|
||||
" RULE(1, READ) {\n"
|
||||
" HAG(foo)\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
/**
|
||||
* Set the username for the authorization tests
|
||||
*/
|
||||
static void setUser(const char *name)
|
||||
{
|
||||
free(asUser);
|
||||
asUser = epicsStrDup(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hostname for the authorization tests
|
||||
*/
|
||||
static void setHost(const char *name)
|
||||
{
|
||||
free(asHost);
|
||||
asHost = epicsStrDup(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the access control system with the given ASG, user, and hostname
|
||||
* This will test that the expected access given by mask is granted
|
||||
* when the Access Security Group (ASG) is interpreted in the
|
||||
* context of the configured user, host, and Level (asl).
|
||||
*/
|
||||
static void testAccess(const char *asg, unsigned mask)
|
||||
{
|
||||
ASMEMBERPVT asp = 0; /* aka dbCommon::asp */
|
||||
@@ -67,18 +587,13 @@ static void testSyntaxErrors(void)
|
||||
long ret;
|
||||
|
||||
testDiag("testSyntaxErrors()");
|
||||
asCheckClientIP = 0;
|
||||
|
||||
eltc(0);
|
||||
ret = asInitMem(empty, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "load \"empty\" config -> %s", errSymMsg(ret));
|
||||
eltc(1);
|
||||
}
|
||||
static const char hostname_config[] = ""
|
||||
"HAG(foo) {localhost}\n"
|
||||
"ASG(DEFAULT) {RULE(0, NONE)}\n"
|
||||
"ASG(ro) {RULE(0, NONE)RULE(1, READ) {HAG(foo)}}\n"
|
||||
"ASG(rw) {RULE(1, WRITE) {HAG(foo)}}\n"
|
||||
;
|
||||
|
||||
static void testHostNames(void)
|
||||
{
|
||||
@@ -144,10 +659,132 @@ static void testUseIP(void)
|
||||
testAccess("rw", 0);
|
||||
}
|
||||
|
||||
static void testFutureProofParser(void)
|
||||
{
|
||||
long ret;
|
||||
|
||||
testDiag("testFutureProofParser()");
|
||||
asCheckClientIP = 0;
|
||||
|
||||
eltc(0); /* Suppress error messages during test */
|
||||
|
||||
/* Test parsing should reject unsupported elements badly placed or formed */
|
||||
ret = asInitMem(unsupported_config_1, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects invalid arg list missing commas -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_config_2, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects invalid string list -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_config_3, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects missing parameters (must have at least an empty arg list) -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_config_4, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects bad arg list for recursive body -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_config_5, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects mix of list and recursive type bodies -> %s", errSymMsg(ret));
|
||||
|
||||
|
||||
/* Test supported elements badly modified should be rejected */
|
||||
ret = asInitMem(unsupported_mod_1, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects bad arg list for ASG element -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_mod_2, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects bad arg list for HAG element-> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_mod_3, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects bad arg list for RULE element -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_mod_4, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects bad arg count for ASG element -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_mod_5, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects unexpected name in arg list for RULE element -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_mod_6, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects unexpected recursive body in HAG element body -> %s", errSymMsg(ret));
|
||||
|
||||
ret = asInitMem(unsupported_mod_7, NULL);
|
||||
testOk(ret==S_asLib_badConfig, "parsing rejects unexpected recursive body in UAG element body -> %s", errSymMsg(ret));
|
||||
|
||||
|
||||
eltc(1);
|
||||
|
||||
/* Test supported for known elements containing unsupported elements, well-formed and ignored */
|
||||
setUser("testing");
|
||||
setHost("localhost");
|
||||
|
||||
ret = asInitMem(supported_config_1, NULL);
|
||||
testOk(ret==0, "unknown elements ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ro", 1);
|
||||
}
|
||||
|
||||
ret = asInitMem(supported_config_2, NULL);
|
||||
testOk(ret==0, "unknown elements with body ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ro", 1);
|
||||
}
|
||||
|
||||
ret = asInitMem(supported_config_3, NULL);
|
||||
testOk(ret==0, "unknown elements with string and double args and a body, ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ro", 1);
|
||||
}
|
||||
|
||||
ret = asInitMem(supported_config_4, NULL);
|
||||
testOk(ret==0, "unknown elements with recursive body ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ro", 1);
|
||||
}
|
||||
|
||||
ret = asInitMem(supported_config_5, NULL);
|
||||
testOk(ret==0, "unknown elements with recursive body with recursion ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ro", 1);
|
||||
}
|
||||
|
||||
ret = asInitMem(supported_config_6, NULL);
|
||||
testOk(ret==0, "unknown elements with keywords arguments and body names ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ignored", 0);
|
||||
testAccess("ro", 1);
|
||||
}
|
||||
|
||||
ret = asInitMem(supported_config_7, NULL);
|
||||
testOk(ret==0, "rules with unknown elements ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ro", 0);
|
||||
}
|
||||
|
||||
ret = asInitMem(supported_config_8, NULL);
|
||||
testOk(ret==0, "rules with unknown permission names ignored -> %s", errSymMsg(ret));
|
||||
if (!ret) {
|
||||
asAsl = 0;
|
||||
testAccess("DEFAULT", 0);
|
||||
testAccess("ro", 0);
|
||||
}
|
||||
}
|
||||
|
||||
MAIN(aslibtest)
|
||||
{
|
||||
testPlan(27);
|
||||
testPlan(64);
|
||||
testSyntaxErrors();
|
||||
testFutureProofParser();
|
||||
testHostNames();
|
||||
testUseIP();
|
||||
errlogFlush();
|
||||
|
||||
Reference in New Issue
Block a user