default:
if ((p[1] >= '0') && (p[1] <= '9') &&
- (sscanf(p, "%3o", &x) == 1)) {
+ (sscanf(p + 1, "%3o", &x) == 1)) {
*q++ = x;
p += 2;
} else {
};
-static int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p)
-
+int radius_get_vp(REQUEST *request, const char *name, VALUE_PAIR **vp_p)
{
const char *vp_name = name;
REQUEST *myrequest = request;
vp_name += 8;
vps = myrequest->config_items;
+#ifdef WITH_COA
+ } else if (strncmp(vp_name, "coa:", 4) == 0) {
+ vp_name += 4;
+
+ if (myrequest->coa &&
+ (myrequest->coa->proxy->code == PW_COA_REQUEST)) {
+ vps = myrequest->coa->proxy->vps;
+ }
+
+ } else if (strncmp(vp_name, "coa-reply:", 10) == 0) {
+ vp_name += 10;
+
+ if (myrequest->coa && /* match reply with request */
+ (myrequest->coa->proxy->code == PW_COA_REQUEST) &&
+ (myrequest->coa->proxy_reply)) {
+ vps = myrequest->coa->proxy_reply->vps;
+ }
+
+ } else if (strncmp(vp_name, "disconnect:", 11) == 0) {
+ vp_name += 11;
+
+ if (myrequest->coa &&
+ (myrequest->coa->proxy->code == PW_DISCONNECT_REQUEST)) {
+ vps = myrequest->coa->proxy->vps;
+ }
+
+ } else if (strncmp(vp_name, "disconnect-reply:", 17) == 0) {
+ vp_name += 17;
+
+ if (myrequest->coa && /* match reply with request */
+ (myrequest->coa->proxy->code == PW_DISCONNECT_REQUEST) &&
+ (myrequest->coa->proxy_reply)) {
+ vps = myrequest->coa->proxy_reply->vps;
+ }
+#endif
+
} else {
vps = myrequest->packet->vps;
}
/*
* May not may not be found, but it *is* a known name.
*/
- *vp_p = pairfind(vps, da->attr);
+ *vp_p = pairfind(vps, da->attr, da->vendor);
return TRUE;
}
int cflags, int modreturn)
{
int result;
- int lint, rint;
+ uint32_t lint, rint;
VALUE_PAIR *vp = NULL;
#ifdef HAVE_REGEX_H
char buffer[1024];
* If so, try looking for it.
*/
da = dict_attrbyname(pleft);
- if (da && radius_find_compare(da->attr)) {
+ if (da && (da->vendor == 0) && radius_find_compare(da->attr)) {
VALUE_PAIR *check = pairmake(pleft, pright, token);
*presult = (radius_callback_compare(request, NULL, check, NULL, NULL) == 0);
+ RDEBUG3(" Callback returns %d",
+ *presult);
pairfree(&check);
- if (*presult) return TRUE;
- return FALSE;
+ return TRUE;
}
RDEBUG2(" (Attribute %s was not found)",
pleft);
- return FALSE;
+ *presult = 0;
+ return TRUE;
}
#ifdef HAVE_REGEX_H
myvp.operator = token;
*presult = paircmp(&myvp, vp);
+ RDEBUG3(" paircmp -> %d", *presult);
return TRUE;
} /* else it's not a VP in a list */
}
RDEBUG2(" (Right field is not a number at: %s)", pright);
return FALSE;
}
- rint = atoi(pright);
+ rint = strtoul(pright, NULL, 0);
if (!all_digits(pleft)) {
RDEBUG2(" (Left field is not a number at: %s)", pleft);
return FALSE;
}
- lint = atoi(pleft);
+ lint = strtoul(pleft, NULL, 0);
break;
default:
* Check for truth or falsehood.
*/
if (all_digits(pleft)) {
- lint = atoi(pleft);
+ lint = strtoul(pleft, NULL, 0);
result = (lint != 0);
} else {
return TRUE;
}
+
int radius_evaluate_condition(REQUEST *request, int modreturn, int depth,
const char **ptr, int evaluate_it, int *presult)
{
while (*p) {
while ((*p == ' ') || (*p == '\t')) p++;
+ /*
+ * ! EXPR
+ */
if (!found_condition && (*p == '!')) {
- RDEBUG4(">>> INVERT");
- invert = TRUE;
+ /*
+ * Don't change the results if we're not
+ * evaluating the condition.
+ */
+ if (evaluate_next_condition) {
+ RDEBUG4(">>> INVERT");
+ invert = TRUE;
+ }
p++;
+
+ while ((*p == ' ') || (*p == '\t')) p++;
}
/*
- * It's a subcondition.
+ * ( EXPR )
*/
if (!found_condition && (*p == '(')) {
const char *end = p + 1;
}
if (invert) {
- if (evaluate_next_condition)
- RDEBUG2("%.*s Converting !%s -> %s",
- depth, filler,
- (result != FALSE) ? "TRUE" : "FALSE",
- (result == FALSE) ? "TRUE" : "FALSE");
-
- result = (result == FALSE);
+ if (evaluate_next_condition) {
+ RDEBUG2("%.*s Converting !%s -> %s",
+ depth, filler,
+ (result != FALSE) ? "TRUE" : "FALSE",
+ (result == FALSE) ? "TRUE" : "FALSE");
+ result = (result == FALSE);
+ }
invert = FALSE;
}
if (*p == ')') p++; /* eat closing brace */
found_condition = TRUE;
- }
- while ((*p == ' ') || (*p == '\t')) p++;
+ while ((*p == ' ') || (*p == '\t')) p++;
+ }
/*
* At EOL or closing brace, update && return.
*
* WORD
* WORD1 op WORD2
- * && condition
- * || condition
+ * && EXPR
+ * || EXPR
*/
if (found_condition) {
/*
*
* WORD1 op WORD2
* WORD )
- * WORD && condition
- * WORD || condition
+ * WORD && EXPR
+ * WORD || EXPR
*/
q = p;
while ((*q == ' ') || (*q == '\t')) q++;
*/
token = gettoken(&p, comp, sizeof(comp));
if ((token < T_OP_NE) || (token > T_OP_CMP_EQ) ||
- (token == T_OP_CMP_TRUE) ||
- (token == T_OP_CMP_FALSE)) {
+ (token == T_OP_CMP_TRUE)) {
radlog(L_ERR, "Expected comparison at: %s", comp);
return FALSE;
}
rt, pright, cflags, modreturn)) {
return FALSE;
}
+ RDEBUG4(">>> Comparison returned %d", result);
if (invert) {
RDEBUG4(">>> INVERTING result");
found_condition = TRUE;
} /* loop over the input condition */
+ if (!found_condition) {
+ radlog(L_ERR, "Syntax error. Expected condition at %s", p);
+ return FALSE;
+ }
+
RDEBUG4(">>> AT EOL -> %d", result);
*ptr = p;
if (evaluate_it) *presult = result;
request->password = NULL;
for (vp = request->packet->vps; vp != NULL; vp = vp->next) {
+ if (vp->vendor != 0) continue;
+
if ((vp->attribute == PW_USER_NAME) &&
!request->username) {
request->username = vp;
} else if (vp->attribute == PW_USER_PASSWORD) {
request->password = vp;
}
+
+ if (request->username && request->password) break;
}
}
+
/*
* The pairmove() function in src/lib/valuepair.c does all sorts of
* extra magic that we don't want here.
found = FALSE;
for (j = 0; j < to_count; j++) {
- if (edited[j]) continue;
+ if (edited[j] || !to_list[j] || !from_list[i]) continue;
/*
* Attributes aren't the same, skip them.
*/
- if (from_list[i]->attribute != to_list[j]->attribute) {
+ if ((from_list[i]->attribute != to_list[j]->attribute) ||
+ (from_list[i]->vendor != to_list[j]->vendor)) {
continue;
}
}
/*
+ * Delete every attribute, independent
+ * of its value.
+ */
+ if (from_list[i]->operator == T_OP_CMP_FALSE) {
+ goto delete;
+ }
+
+ /*
* Delete all matching attributes from
* "to"
*/
last = &(*last)->next;
}
+ rad_assert(request != NULL);
+ rad_assert(request->packet != NULL);
+
/*
* Fix dumb cache issues
*/
CONF_ITEM *ci;
VALUE_PAIR *newlist, *vp;
VALUE_PAIR **output_vps = NULL;
- REQUEST *request_vps = request;
+ REQUEST *myrequest = request;
if (!request || !cs) return RLM_MODULE_INVALID;
if (strncmp(name, "outer.", 6) == 0) {
if (!request->parent) return RLM_MODULE_NOOP;
- request_vps = request->parent;
+ myrequest = request->parent;
name += 6;
}
if (strcmp(name, "request") == 0) {
- output_vps = &request_vps->packet->vps;
+ output_vps = &myrequest->packet->vps;
} else if (strcmp(name, "reply") == 0) {
- output_vps = &request_vps->reply->vps;
+ output_vps = &myrequest->reply->vps;
#ifdef WITH_PROXY
} else if (strcmp(name, "proxy-request") == 0) {
- if (request->proxy) output_vps = &request_vps->proxy->vps;
+ if (request->proxy) output_vps = &myrequest->proxy->vps;
} else if (strcmp(name, "proxy-reply") == 0) {
if (request->proxy_reply) output_vps = &request->proxy_reply->vps;
#endif
} else if (strcmp(name, "config") == 0) {
- output_vps = &request_vps->config_items;
+ output_vps = &myrequest->config_items;
} else if (strcmp(name, "control") == 0) {
- output_vps = &request_vps->config_items;
+ output_vps = &myrequest->config_items;
+
+#ifdef WITH_COA
+ } else if (strcmp(name, "coa") == 0) {
+ if (!myrequest->coa) {
+ request_alloc_coa(myrequest);
+ myrequest->coa->proxy->code = PW_COA_REQUEST;
+ }
+
+ if (myrequest->coa &&
+ (myrequest->coa->proxy->code == PW_COA_REQUEST)) {
+ output_vps = &myrequest->coa->proxy->vps;
+ }
+
+ } else if (strcmp(name, "coa-reply") == 0) {
+ if (myrequest->coa && /* match reply with request */
+ (myrequest->coa->proxy->code == PW_COA_REQUEST) &&
+ (myrequest->coa->proxy_reply)) {
+ output_vps = &myrequest->coa->proxy_reply->vps;
+ }
+
+ } else if (strcmp(name, "disconnect") == 0) {
+ if (!myrequest->coa) {
+ request_alloc_coa(myrequest);
+ if (myrequest->coa) myrequest->coa->proxy->code = PW_DISCONNECT_REQUEST;
+ }
+
+ if (myrequest->coa &&
+ (myrequest->coa->proxy->code == PW_DISCONNECT_REQUEST)) {
+ output_vps = &myrequest->coa->proxy->vps;
+ }
+
+ } else if (strcmp(name, "disconnect-reply") == 0) {
+ if (myrequest->coa && /* match reply with request */
+ (myrequest->coa->proxy->code == PW_DISCONNECT_REQUEST) &&
+ (myrequest->coa->proxy_reply)) {
+ output_vps = &myrequest->coa->proxy_reply->vps;
+ }
+#endif
} else {
return RLM_MODULE_INVALID;
cp = cf_itemtopair(ci);
+#ifndef NDEBUG
+ if (debug_flag && (vp->vendor == 0) &&
+ radius_find_compare(vp->attribute)) {
+ DEBUG("WARNING: You are modifying the value of virtual attribute %s. This is not supported.", vp->name);
+ }
+#endif
+
/*
* The VP && CF lists should be in sync. If they're
* not, panic.