X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=src%2Fmodules%2Frlm_policy%2Fevaluate.c;h=3c1a000c6fffc3f1284c72c9fd3a88e90fadf36d;hb=9960563934a7da222528a1d82224aecc207c8aa8;hp=ca355dec2790e5a8c9a131652517977225340230;hpb=d20c92703a0aaeea2b5dce449300b7726362c3f1;p=freeradius.git diff --git a/src/modules/rlm_policy/evaluate.c b/src/modules/rlm_policy/evaluate.c index ca355de..3c1a000 100644 --- a/src/modules/rlm_policy/evaluate.c +++ b/src/modules/rlm_policy/evaluate.c @@ -38,50 +38,50 @@ RCSID("$Id$") static void policy_print(const policy_item_t *item, int indent) { if (!item) { - if (indent) printf("%*s", indent, " "); - printf("[NULL]\n"); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "[NULL]\n"); return; } - + while (item) { switch (item->type) { case POLICY_TYPE_BAD: - if (indent) printf("%*s", indent, " "); - printf("[BAD STATEMENT]"); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "[BAD STATEMENT]"); break; - + case POLICY_TYPE_PRINT: - if (indent) printf("%*s", indent, " "); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); { const policy_print_t *this; this = (const policy_print_t *) item; - + if (this->rhs_type == POLICY_LEX_BARE_WORD) { - printf("print %s\n", this->rhs); + fprintf(fr_log_fp, "print %s\n", this->rhs); } else { - printf("print \"%s\"\n", this->rhs); + fprintf(fr_log_fp, "print \"%s\"\n", this->rhs); } } break; - + case POLICY_TYPE_ASSIGNMENT: { const policy_assignment_t *assign; - + assign = (const policy_assignment_t *) item; - if (indent) printf("%*s", indent, " "); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); - printf("\t%s %s ", assign->lhs, - lrad_int2str(rlm_policy_tokens, + fprintf(fr_log_fp, "\t%s %s ", assign->lhs, + fr_int2str(rlm_policy_tokens, assign->assign, "?")); if (assign->rhs_type == POLICY_LEX_BARE_WORD) { - printf("%s\n", assign->rhs); + fprintf(fr_log_fp, "%s\n", assign->rhs); } else { /* * FIXME: escape " */ - printf("\"%s\"\n", assign->rhs); + fprintf(fr_log_fp, "\"%s\"\n", assign->rhs); } } break; @@ -92,61 +92,65 @@ static void policy_print(const policy_item_t *item, int indent) condition = (const policy_condition_t *) item; - printf("("); + fprintf(fr_log_fp, "("); + + if (condition->sense) { + fprintf(fr_log_fp, "!"); + } /* * Nested conditions. */ if (condition->compare == POLICY_LEX_L_BRACKET) { policy_print(condition->child, indent); - printf(")"); + fprintf(fr_log_fp, ")"); break; } if (condition->compare == POLICY_LEX_L_NOT) { - printf("!"); + fprintf(fr_log_fp, "!"); policy_print(condition->child, indent); - printf(")"); + fprintf(fr_log_fp, ")"); break; } if (condition->compare == POLICY_LEX_CMP_TRUE) { - printf("%s)", condition->lhs); + fprintf(fr_log_fp, "%s)", condition->lhs); break; } if (condition->lhs_type == POLICY_LEX_FUNCTION) { - printf("%s()", condition->lhs); + fprintf(fr_log_fp, "%s()", condition->lhs); } else { /* * FIXME: escape ", * and move all of this logic * to a function. */ - printf("\"%s\"", condition->lhs); + fprintf(fr_log_fp, "\"%s\"", condition->lhs); } /* * We always print this condition. */ - printf(" %s ", lrad_int2str(rlm_policy_tokens, + fprintf(fr_log_fp, " %s ", fr_int2str(rlm_policy_tokens, condition->compare, "?")); if (condition->rhs_type == POLICY_LEX_BARE_WORD) { - printf("%s", condition->rhs); + fprintf(fr_log_fp, "%s", condition->rhs); } else { /* * FIXME: escape ", * and move all of this logic * to a function. */ - printf("\"%s\"", condition->rhs); + fprintf(fr_log_fp, "\"%s\"", condition->rhs); } - printf(")"); - + fprintf(fr_log_fp, ")"); + if ((condition->child_condition != POLICY_LEX_BAD) && (condition->child_condition != POLICY_LEX_BARE_WORD)) { - printf(" %s ", lrad_int2str(rlm_policy_tokens, condition->child_condition, "?")); + fprintf(fr_log_fp, " %s ", fr_int2str(rlm_policy_tokens, condition->child_condition, "?")); policy_print(condition->child, indent); } } @@ -158,24 +162,24 @@ static void policy_print(const policy_item_t *item, int indent) statement = (const policy_if_t *) item; - if (indent) printf("%*s", indent, " "); - printf("if "); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "if "); policy_print(statement->condition, indent); - printf(" {\n"); + fprintf(fr_log_fp, " {\n"); policy_print(statement->if_true, indent + 1); - if (indent) printf("%*s", indent, " "); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); if (statement->if_false) { - printf("} else "); + fprintf(fr_log_fp, "} else "); if (statement->if_false->type == POLICY_TYPE_ASSIGNMENT) { - printf(" { "); + fprintf(fr_log_fp, " { "); policy_print(statement->if_false, indent + 1); - if (indent) printf("%*s", indent, " "); - printf(" }"); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, " }"); } else { policy_print(statement->if_false, indent + 1); } } else { - printf("}\n"); + fprintf(fr_log_fp, "}\n"); } } break; @@ -186,15 +190,15 @@ static void policy_print(const policy_item_t *item, int indent) this = (const policy_attributes_t *) item; - if (indent) printf("%*s", indent, " "); - printf("%s %s {\n", - lrad_int2str(policy_reserved_words, + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "%s %s {\n", + fr_int2str(policy_reserved_words, this->where, "?"), - lrad_int2str(rlm_policy_tokens, + fr_int2str(rlm_policy_tokens, this->how, "?")); policy_print(this->attributes, indent + 1); - if (indent) printf("%*s", indent, " "); - printf("}\n"); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "}\n"); } break; @@ -203,11 +207,11 @@ static void policy_print(const policy_item_t *item, int indent) const policy_named_t *this; this = (const policy_named_t *) item; - if (indent) printf("%*s", indent, " "); - printf("policy %s {\n", this->name); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "policy %s {\n", this->name); policy_print(this->policy, indent + 1); - if (indent) printf("%*s", indent, " "); - printf("}\n"); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "}\n"); } break; @@ -216,8 +220,8 @@ static void policy_print(const policy_item_t *item, int indent) const policy_call_t *this; this = (const policy_call_t *) item; - if (indent) printf("%*s", indent, " "); - printf("call %s\n", this->name); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "call %s\n", this->name); } break; @@ -226,9 +230,9 @@ static void policy_print(const policy_item_t *item, int indent) const policy_return_t *this; this = (const policy_return_t *) item; - if (indent) printf("%*s", indent, " "); - printf("return %s\n", - lrad_int2str(policy_return_codes, + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "return %s\n", + fr_int2str(policy_return_codes, this->rcode, "???")); } break; @@ -238,18 +242,18 @@ static void policy_print(const policy_item_t *item, int indent) const policy_module_t *this; this = (const policy_module_t *) item; - if (indent) printf("%*s", indent, " "); - printf("module %s \n", - lrad_int2str(policy_component_names, + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "module %s \n", + fr_int2str(policy_component_names, this->component, "???")); } break; default: - if (indent) printf("%*s", indent, " "); - printf("[HUH?]\n"); + if (indent) fprintf(fr_log_fp, "%*s", indent, " "); + fprintf(fr_log_fp, "[HUH?]\n"); break; - + } item = item->next; @@ -259,9 +263,10 @@ static void policy_print(const policy_item_t *item, int indent) void rlm_policy_print(const policy_item_t *item) { - printf("----------------------------------------------------------\n"); + if (!fr_log_fp) return; + + fprintf(fr_log_fp, "# rlm_policy \n"); policy_print(item, 0); - printf("----------------------------------------------------------\n"); } /* @@ -386,16 +391,19 @@ static int evaluate_print(policy_state_t *state, const policy_item_t *item) { const policy_print_t *this; + if (!fr_log_fp) return 1; + this = (const policy_print_t *) item; if (this->rhs_type == POLICY_LEX_BARE_WORD) { - printf("%s\n", this->rhs); + fprintf(fr_log_fp, "%s\n", this->rhs); } else { char buffer[1024]; radius_xlat(buffer, sizeof(buffer), this->rhs, state->request, NULL); - printf("%s", buffer); + fprintf(fr_log_fp, "%s", buffer); + if (!strchr(buffer, '\n')) fprintf(fr_log_fp, "\n"); } /* @@ -430,6 +438,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name) } else if (strncasecmp(name, "reply:", 6) == 0) { p += 6; vps = request->reply->vps; +#ifdef WITH_PROXY } else if (strncasecmp(name, "proxy-request:", 14) == 0) { p += 14; if (request->proxy) { @@ -440,6 +449,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name) if (request->proxy_reply) { vps = request->proxy_reply->vps; } +#endif } else if (strncasecmp(name, "control:", 8) == 0) { p += 8; vps = request->config_items; @@ -455,7 +465,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name) return NULL; /* no such attribute */ } - return pairfind(vps, dattr->attr); + return pairfind(vps, dattr->attr, dattr->vendor); } @@ -464,7 +474,7 @@ static VALUE_PAIR *find_vp(REQUEST *request, const char *name) * * Not really used much... */ -static int evaluate_assignment(policy_state_t *state, const policy_item_t *item) +static int evaluate_assignment(UNUSED policy_state_t *state, const policy_item_t *item) { const policy_assignment_t *this; #if 0 @@ -519,7 +529,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) * evaluate all of it... */ rcode = policy_evaluate_name(state, this->lhs); - data = lrad_int2str(policy_return_codes, rcode, "???"); + data = fr_int2str(policy_return_codes, rcode, "???"); strlcpy(lhs_buffer, data, sizeof(lhs_buffer)); /* FIXME: yuck */ } else if (this->lhs_type == POLICY_LEX_DOUBLE_QUOTED_STRING) { if (radius_xlat(lhs_buffer, sizeof(lhs_buffer), this->lhs, @@ -528,7 +538,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) } } } - + switch (this->compare) { case POLICY_LEX_L_BRACKET: /* nested brackets are a special case */ rcode = evaluate_condition(state, this->child); @@ -579,10 +589,13 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) vp = find_vp(state->request, this->lhs); /* - * A op B always returns FALSE if A doesn't + * A op B is FALSE if A doesn't * exist. */ - if (!vp) return FALSE; /* not in the request */ + if (!vp) { + rcode = FALSE; + break; + } /* * FIXME: Move sanity checks to @@ -591,6 +604,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) */ vp_prints_value(buffer, sizeof(buffer), vp, 0); myvp = pairmake(vp->name, this->rhs, T_OP_EQ); + if (!myvp) return FALSE; /* memory failure */ data = buffer; /* @@ -605,56 +619,57 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) * error codes than "comparison is less * than, equal to, or greater than zero". */ - compare = simplepaircmp(state->request, - vp, myvp); + compare = radius_callback_compare(state->request, + vp, myvp, NULL, NULL); pairfree(&myvp); - + } else { /* * FIXME: Do something for RHS type? */ - printf("CMP %s %s\n", lhs_buffer, this->rhs); + fr_printf_log("CMP %s %s\n", lhs_buffer, this->rhs); compare = strcmp(lhs_buffer, this->rhs); } debug_evaluate("CONDITION COMPARE %d\n", compare); - + switch (this->compare) { case POLICY_LEX_CMP_EQUALS: rcode = (compare == 0); break; - + case POLICY_LEX_CMP_NOT_EQUALS: rcode = (compare != 0); break; - + case POLICY_LEX_LT: rcode = (compare < 0); break; - + case POLICY_LEX_GT: rcode = (compare > 0); break; - + case POLICY_LEX_LE: rcode =(compare <= 0); break; - + case POLICY_LEX_GE: rcode = (compare >= 0); break; - + #ifdef HAVE_REGEX_H case POLICY_LEX_RX_EQUALS: { /* FIXME: copied from src/main/valuepair.c */ int i; regmatch_t rxmatch[REQUEST_MAX_REGEX + 1]; - + /* * Include substring matches. */ if (regcomp(®, this->rhs, REG_EXTENDED) != 0) { + /* FIXME: print error */ return FALSE; } rad_assert(data != NULL); @@ -663,14 +678,14 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) rxmatch, 0); rcode = (rcode == 0); regfree(®); - + /* * Add %{0}, %{1}, etc. */ for (i = 0; i <= REQUEST_MAX_REGEX; i++) { char *p; char rxbuffer[256]; - + /* * Didn't match: delete old * match, if it existed. @@ -683,14 +698,14 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) free(p); continue; } - + /* * No previous match * to delete, stop. */ break; } - + /* * Copy substring into buffer. */ @@ -698,7 +713,7 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) data + rxmatch[i].rm_so, rxmatch[i].rm_eo - rxmatch[i].rm_so); rxbuffer[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0'; - + /* * Copy substring, and add it to * the request. @@ -713,10 +728,10 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) REQUEST_DATA_REGEX | i, p, free); } - + } break; - + case POLICY_LEX_RX_NOT_EQUALS: regcomp(®, this->rhs, REG_EXTENDED|REG_NOSUB); rad_assert(data != NULL); @@ -733,6 +748,8 @@ static int evaluate_condition(policy_state_t *state, const policy_item_t *item) break; /* default from first switch over compare */ } + if (this->sense) rcode = (rcode == FALSE); /* reverse sense of test */ + /* * No trailing &&, || */ @@ -800,7 +817,7 @@ static VALUE_PAIR *assign2vp(REQUEST *request, const policy_assignment_t *assign) { VALUE_PAIR *vp; - LRAD_TOKEN operator = T_OP_EQ; + FR_TOKEN operator = T_OP_EQ; const char *value = assign->rhs; char buffer[2048]; @@ -822,22 +839,22 @@ static VALUE_PAIR *assign2vp(REQUEST *request, case POLICY_LEX_SET_EQUALS: operator = T_OP_SET; break; - + case POLICY_LEX_PLUS_EQUALS: operator = T_OP_ADD; break; - + default: fprintf(stderr, "Expected '=' for operator, not '%s' at line %d\n", - lrad_int2str(rlm_policy_tokens, + fr_int2str(rlm_policy_tokens, assign->assign, "?"), assign->item.lineno); return NULL; } - + vp = pairmake(assign->lhs, value, operator); if (!vp) { - fprintf(stderr, "SHIT: %s %s\n", value, librad_errstr); + fprintf(stderr, "Failed creating pair: %s %s\n", value, fr_strerror()); } return vp; @@ -853,6 +870,7 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item) VALUE_PAIR **vps = NULL; VALUE_PAIR *vp, *head, **tail; const policy_item_t *attr; + policy_lex_t this_how; this = (const policy_attributes_t *) item; @@ -869,6 +887,7 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item) vps = &(state->request->reply->vps); break; +#ifdef WITH_PROXY case POLICY_RESERVED_PROXY_REQUEST: if (!state->request->proxy) return 0; /* FIXME: print error */ vps = &(state->request->proxy->vps); @@ -878,6 +897,7 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item) if (!state->request->proxy_reply) return 0; /* FIXME: print error */ vps = &(state->request->proxy_reply->vps); break; +#endif default: return 0; @@ -903,21 +923,121 @@ static int evaluate_attr_list(policy_state_t *state, const policy_item_t *item) tail = &(vp->next); } - switch (this->how) { + this_how = this->how; + retry_how: + switch (this_how) { case POLICY_LEX_SET_EQUALS: /* dangerous: removes all previous things! */ pairfree(vps); *vps = head; break; + case POLICY_LEX_AFTER_TAIL_ASSIGN: + pairmove(vps, &head); + pairfree(&head); + break; + case POLICY_LEX_ASSIGN: /* 'union' */ pairmove(vps, &head); pairfree(&head); break; + case POLICY_LEX_BEFORE_HEAD_ASSIGN: + pairmove(&head, vps); + pairfree(vps); + *vps = head; + break; + + case POLICY_LEX_AFTER_TAIL_EQUALS: case POLICY_LEX_CONCAT_EQUALS: pairadd(vps, head); break; + case POLICY_LEX_BEFORE_HEAD_EQUALS: + pairadd(&head, *vps); + *vps = head; + break; + + case POLICY_LEX_BEFORE_WHERE_EQUALS: + case POLICY_LEX_AFTER_WHERE_EQUALS: + case POLICY_LEX_BEFORE_WHERE_ASSIGN: + case POLICY_LEX_AFTER_WHERE_ASSIGN: + /* find location*/ + { + VALUE_PAIR *vpprev = NULL, *vpnext = NULL, *lvp; + + for(lvp = *vps; lvp; vpprev = lvp, lvp = lvp->next) { + vpnext = lvp->next; + lvp->next = NULL; + if (evaluate_condition(state, this->where_loc)) + break; + lvp->next = vpnext; + } + + if (lvp) { + switch(this_how) { + case POLICY_LEX_BEFORE_WHERE_EQUALS: + case POLICY_LEX_BEFORE_WHERE_ASSIGN: + if (vpprev) { + lvp->next = vpnext; + vpnext = lvp; + vpprev->next = NULL; + lvp = vpprev; + } + default: /* always reached */ + break; + } + + switch(this_how) { + case POLICY_LEX_BEFORE_WHERE_EQUALS: + if (vpprev) + pairadd(&lvp, head); + else + *vps = lvp = head; + break; + case POLICY_LEX_AFTER_WHERE_EQUALS: + pairadd(&lvp, head); + break; + case POLICY_LEX_BEFORE_WHERE_ASSIGN: + if (vpprev) { + pairmove(&lvp, &head); + pairfree(&head); + } + else + *vps = lvp = head; + break; + case POLICY_LEX_AFTER_WHERE_ASSIGN: + pairmove(&lvp, &head); + pairfree(&head); + break; + default:/*never reached*/ + break; + } + for( ; lvp && lvp->next; lvp = lvp->next); + if (lvp) + lvp->next = vpnext; + break; + } + + switch(this_how) { + case POLICY_LEX_BEFORE_WHERE_EQUALS: + this_how = POLICY_LEX_BEFORE_HEAD_EQUALS; + break; + case POLICY_LEX_AFTER_WHERE_EQUALS: + this_how = POLICY_LEX_AFTER_TAIL_EQUALS; + break; + case POLICY_LEX_BEFORE_WHERE_ASSIGN: + this_how = POLICY_LEX_BEFORE_HEAD_ASSIGN; + break; + case POLICY_LEX_AFTER_WHERE_ASSIGN: + this_how = POLICY_LEX_AFTER_TAIL_ASSIGN; + break; + default: /*never reached*/ + break; + } + goto retry_how; + } + /* FALL-THROUGH */ + default: fprintf(stderr, "HUH?\n"); pairfree(&head); @@ -943,9 +1063,9 @@ static int evaluate_call(policy_state_t *state, const policy_item_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); @@ -982,7 +1102,7 @@ static int evaluate_return(policy_state_t *state, const policy_item_t *item) this = (const policy_return_t *) item; state->rcode = this->rcode; - + return 1; /* we succeeded */ } @@ -1008,7 +1128,7 @@ static int evaluate_module(policy_state_t *state, const policy_item_t *item) DEBUG2("rlm_policy: begin nested call"); state->rcode = modcall(this->component, this->mc, state->request); DEBUG2("rlm_policy: end nested call"); - + return 1; /* we succeeded */ } @@ -1044,16 +1164,16 @@ static int policy_evaluate_name(policy_state_t *state, const char *name) int rcode; const policy_item_t *this; policy_named_t mypolicy, *policy; - + mypolicy.name = name; policy = rbtree_finddata(state->inst->policies, &mypolicy); if (!policy) return RLM_MODULE_FAIL; - + DEBUG2("rlm_policy: Evaluating policy %s", name); - + rad_assert(policy->item.type != POLICY_TYPE_BAD); rad_assert(policy->item.type < POLICY_TYPE_NUM_TYPES); - + rcode = policy_stack_push(state, policy->policy); if (!rcode) { return RLM_MODULE_FAIL; @@ -1067,7 +1187,7 @@ static int policy_evaluate_name(policy_state_t *state, const char *name) rad_assert(this != NULL); rad_assert(this->type != POLICY_TYPE_BAD); rad_assert(this->type < POLICY_TYPE_NUM_TYPES); - + debug_evaluate("Evaluating at line %d\n", this->lineno); rcode = (*evaluate_functions[this->type])(state, @@ -1095,7 +1215,7 @@ int rlm_policy_evaluate(rlm_policy_t *inst, REQUEST *request, const char *name) state->request = request; state->inst = inst; state->rcode = RLM_MODULE_OK; - state->component = lrad_str2int(policy_component_names, name, + state->component = fr_str2int(policy_component_names, name, RLM_COMPONENT_COUNT); rcode = policy_evaluate_name(state, name);