/* * Evaluate a reference call to a module. */ static int evaluate_call(policy_state_t *state, const policy_item_t *item) { int rcode; const policy_call_t *this; const policy_named_t *policy; this = (const policy_call_t *) item; policy = rlm_policy_find(state->inst->policies, this->name); if (!policy) return 0; /* not found... */ DEBUG2("rlm_policy: Evaluating policy %s", this->name); rad_assert(policy->policy->type != POLICY_TYPE_BAD); rad_assert(policy->policy->type < POLICY_TYPE_NUM_TYPES); /* * Push the name of the function onto the stack, * so that we can catch recursive calls. * * The "pop" function will skip over it when it sees it. */ rcode = policy_stack_push(state, (const policy_item_t *) policy); if (!rcode) { return rcode; } /* * Push it onto the stack. Other code will take care of * calling it. */ rcode = policy_stack_push(state, policy->policy); if (!rcode) { return rcode; } return 1; }
/* * (foo == bar), with nested conditionals. */ static int parse_condition(policy_lex_file_t *lexer, policy_item_t **tail) { int rcode, seen_not = FALSE; policy_lex_t token, compare; char lhs[256], rhs[256]; policy_condition_t *this; token = policy_lex_file(lexer, 0, lhs, sizeof(lhs)); if (token != POLICY_LEX_L_BRACKET) { fprintf(stderr, "%s[%d]: Expected '(', got \"%s\"\n", lexer->filename, lexer->lineno, fr_int2str(rlm_policy_tokens, token, lhs)); return 0; } this = rad_malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->item.type = POLICY_TYPE_CONDITIONAL; this->item.lineno = lexer->lineno; redo: token = policy_lex_file(lexer, 0, lhs, sizeof(lhs)); switch (token) { case POLICY_LEX_L_BRACKET: if (!policy_lex_push_token(lexer, token)) { rlm_policy_free_item((policy_item_t *) this); return 0; } this->compare = POLICY_LEX_L_BRACKET; this->child_condition = POLICY_LEX_L_BRACKET; rcode = parse_condition(lexer, &(this->child)); if (!rcode) { rlm_policy_free_item((policy_item_t *) this); return rcode; } break; case POLICY_LEX_L_NOT: if (seen_not) { fprintf(stderr, "%s[%d]: Syntax error at \"!!\"\n", lexer->filename, lexer->lineno); rlm_policy_free_item((policy_item_t *) this); return 0; } debug_tokens("[NOT] "); token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0); if (token != POLICY_LEX_L_BRACKET) { seen_not = this->sense = 1; goto redo; } this->compare = POLICY_LEX_L_NOT; rcode = parse_condition(lexer, &(this->child)); if (!rcode) { rlm_policy_free_item((policy_item_t *) this); return rcode; } break; case POLICY_LEX_BARE_WORD: this->lhs_type = token; token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0); if (token == POLICY_LEX_L_BRACKET) { debug_tokens("[IF-CALL %s] ", lhs); /* * Function call. */ if (rlm_policy_find(lexer->policies, lhs) == NULL) { fprintf(stderr, "%s[%d]: Undefined function \"%s\"\n", lexer->filename, lexer->lineno, lhs); rlm_policy_free_item((policy_item_t *) this); return 0; } /* * this->lhs set up below, after "check" */ this->lhs_type = POLICY_LEX_FUNCTION; /* * Copied from parse_call */ token = policy_lex_file(lexer, 0, NULL, 0); if (token != POLICY_LEX_L_BRACKET) { fprintf(stderr, "%s[%d]: Expected left bracket, got \"%s\"\n", lexer->filename, lexer->lineno, fr_int2str(rlm_policy_tokens, token, "?")); rlm_policy_free_item((policy_item_t *) this); return 0; } token = policy_lex_file(lexer, 0, NULL, 0); if (token != POLICY_LEX_R_BRACKET) { fprintf(stderr, "%s[%d]: Expected right bracket, got \"%s\"\n", lexer->filename, lexer->lineno, fr_int2str(rlm_policy_tokens, token, "?")); rlm_policy_free_item((policy_item_t *) this); return 0; } } /* else it's a comparison? */ goto check; case POLICY_LEX_DOUBLE_QUOTED_STRING: this->lhs_type = token; /* * Got word. May just be test for existence. */ check: token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0); if (token == POLICY_LEX_R_BRACKET) { debug_tokens("[TEST %s] ", lhs); this->lhs = strdup(lhs); this->compare = POLICY_LEX_CMP_TRUE; break; } compare = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); switch (compare) { case POLICY_LEX_CMP_EQUALS: case POLICY_LEX_CMP_NOT_EQUALS: case POLICY_LEX_RX_EQUALS: case POLICY_LEX_RX_NOT_EQUALS: case POLICY_LEX_CMP_TRUE: case POLICY_LEX_CMP_FALSE: case POLICY_LEX_LT: case POLICY_LEX_GT: case POLICY_LEX_LE: case POLICY_LEX_GE: break; default: fprintf(stderr, "%s[%d]: Invalid operator \"%s\"\n", lexer->filename, lexer->lineno, fr_int2str(rlm_policy_tokens, compare, rhs)); rlm_policy_free_item((policy_item_t *) this); return 0; } token = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); if ((token != POLICY_LEX_BARE_WORD) && (token != POLICY_LEX_DOUBLE_QUOTED_STRING)) { fprintf(stderr, "%s[%d]: Unexpected rhs token\n", lexer->filename, lexer->lineno); rlm_policy_free_item((policy_item_t *) this); return 0; } debug_tokens("[COMPARE (%s %s %s)] ", lhs, fr_int2str(rlm_policy_tokens, compare, "?"), rhs); this->lhs = strdup(lhs); this->compare = compare; this->rhs_type = token; this->rhs = strdup(rhs); break; default: fprintf(stderr, "%s[%d]: Unexpected lhs token\n", lexer->filename, lexer->lineno); rlm_policy_free_item((policy_item_t *) this); return 0; } token = policy_lex_file(lexer, 0, NULL, 0); if (token != POLICY_LEX_R_BRACKET) { fprintf(stderr, "%s[%d]: Expected ')', got \"%s\"\n", lexer->filename, lexer->lineno, fr_int2str(rlm_policy_tokens, token, "?")); rlm_policy_free_item((policy_item_t *) this); return 0; } /* * After the end of condition, we MAY have && or || */ token = policy_lex_file(lexer, POLICY_LEX_FLAG_PEEK, NULL, 0); if ((token == POLICY_LEX_L_AND) || (token == POLICY_LEX_L_OR)) { token = policy_lex_file(lexer, 0, NULL, 0); /* skip over it */ debug_tokens("[%s] ", fr_int2str(rlm_policy_tokens, token, "?")); this->child_condition = token; rcode = parse_condition(lexer, &(this->child)); if (!rcode) { rlm_policy_free_item((policy_item_t *) this); return 0; } } *tail = (policy_item_t *) this; return 1; }
/* * Parse one statement. 'foo = bar', or 'if (...) {...}', or '{...}', * and so on. */ static int parse_statement(policy_lex_file_t *lexer, policy_item_t **tail) { int rcode; policy_reserved_word_t reserved; policy_lex_t token, assign; char lhs[256], rhs[256]; policy_assignment_t *this; /* * See what kind of token we have. */ token = policy_lex_file(lexer, 0, lhs, sizeof(lhs)); switch (token) { case POLICY_LEX_LC_BRACKET: rcode = parse_block(lexer, tail); if (!rcode) { return 0; } break; case POLICY_LEX_BARE_WORD: reserved = fr_str2int(policy_reserved_words, lhs, POLICY_RESERVED_UNKNOWN); switch (reserved) { case POLICY_RESERVED_IF: if (parse_if(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_CONTROL: case POLICY_RESERVED_REQUEST: case POLICY_RESERVED_REPLY: case POLICY_RESERVED_PROXY_REQUEST: case POLICY_RESERVED_PROXY_REPLY: if (parse_attribute_block(lexer, tail, reserved)) return 1; return 0; break; case POLICY_RESERVED_PRINT: if (parse_print(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_RETURN: if (parse_return(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_MODULE: if (parse_module(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_UNKNOWN: /* wasn't a reserved word */ /* * Is a named policy, parse the reference to it. */ if (rlm_policy_find(lexer->policies, lhs) != NULL) { if (!parse_call(lexer, tail, lhs)) { return 0; } return 1; } { const DICT_ATTR *dattr; /* * Bare words MUST be dictionary attributes */ dattr = dict_attrbyname(lhs); if (!dattr) { fprintf(stderr, "%s[%d]: Expected attribute name, got \"%s\"\n", lexer->filename, lexer->lineno, lhs); return 0; } debug_tokens("%s[%d]: Got attribute %s\n", lexer->filename, lexer->lineno, lhs); } break; default: fprintf(stderr, "%s[%d]: Unexpected reserved word \"%s\"\n", lexer->filename, lexer->lineno, lhs); return 0; } /* switch over reserved words */ break; /* * Return from nested blocks. */ case POLICY_LEX_RC_BRACKET: policy_lex_push_token(lexer, token); return 2; /* magic */ case POLICY_LEX_EOF: /* nothing more to do */ return 3; default: fprintf(stderr, "%s[%d]: Unexpected %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, token, "string")); break; } /* * Parse a bare statement. */ assign = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); switch (assign) { case POLICY_LEX_ASSIGN: case POLICY_LEX_SET_EQUALS: case POLICY_LEX_AND_EQUALS: case POLICY_LEX_OR_EQUALS: case POLICY_LEX_PLUS_EQUALS: break; default: fprintf(stderr, "%s[%d]: Unexpected assign %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, assign, "string")); return 0; } this = rad_malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->item.type = POLICY_TYPE_ASSIGNMENT; this->item.lineno = lexer->lineno; token = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); if ((token != POLICY_LEX_BARE_WORD) && (token != POLICY_LEX_DOUBLE_QUOTED_STRING)) { fprintf(stderr, "%s[%d]: Unexpected rhs %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, token, "string")); rlm_policy_free_item((policy_item_t *) this); return 0; } this->rhs_type = token; this->rhs = strdup(rhs); token = policy_lex_file(lexer, POLICY_LEX_FLAG_RETURN_EOL, rhs, sizeof(rhs)); if (token != POLICY_LEX_EOL) { fprintf(stderr, "%s[%d]: Expected EOL\n", lexer->filename, lexer->lineno); rlm_policy_free_item((policy_item_t *) this); return 0; } debug_tokens("[ASSIGN %s %s %s]\n", lhs, fr_int2str(rlm_policy_tokens, assign, "?"), rhs); /* * Fill in the assignment struct */ this->lhs = strdup(lhs); this->assign = assign; *tail = (policy_item_t *) this; return 1; }