/** Print a map to a string * * @param[out] buffer for the output string * @param[in] bufsize of the buffer * @param[in] map to print * @return the size of the string printed */ size_t radius_map2str(char *buffer, size_t bufsize, value_pair_map_t const *map) { size_t len; char *p = buffer; char *end = buffer + bufsize; len = radius_tmpl2str(buffer, bufsize, map->dst); p += len; *(p++) = ' '; strlcpy(p, fr_token_name(map->op), end - p); p += strlen(p); *(p++) = ' '; /* * The RHS doesn't matter for many operators */ if ((map->op == T_OP_CMP_TRUE) || (map->op == T_OP_CMP_FALSE)) { strlcpy(p, "ANY", (end - p)); p += strlen(p); return p - buffer; } rad_assert(map->src != NULL); len = radius_tmpl2str(p, end - p, map->src); p += len; return p - buffer; }
/** Print a map to a string * * @param[out] buffer for the output string * @param[in] bufsize of the buffer * @param[in] map to print * @return the size of the string printed */ size_t radius_map2str(char *buffer, size_t bufsize, value_pair_map_t const *map) { size_t len; char *p = buffer; char *end = buffer + bufsize; len = radius_tmpl2str(buffer, bufsize, map->dst); p += len; *(p++) = ' '; strlcpy(p, fr_token_name(map->op), end - p); p += strlen(p); *(p++) = ' '; /* * The RHS doesn't matter for many operators */ if ((map->op == T_OP_CMP_TRUE) || (map->op == T_OP_CMP_FALSE)) { strlcpy(p, "ANY", (end - p)); p += strlen(p); return p - buffer; } rad_assert(map->src != NULL); if ((map->dst->type == VPT_TYPE_ATTR) && (map->dst->da->type == PW_TYPE_STRING) && (map->src->type == VPT_TYPE_LITERAL)) { *(p++) = '\''; len = radius_tmpl2str(p, end - p, map->src); p += len; *(p++) = '\''; *p = '\0'; } else { len = radius_tmpl2str(p, end - p, map->src); p += len; } return p - buffer; }
/* * *presult is "did comparison match or not" */ static int radius_do_cmp(REQUEST *request, int *presult, FR_TOKEN lt, const char *pleft, FR_TOKEN token, FR_TOKEN rt, const char *pright, int cflags, int modreturn) { int result; uint32_t lint, rint; VALUE_PAIR *vp = NULL; #ifdef HAVE_REGEX_H char buffer[8192]; #else cflags = cflags; /* -Wunused */ #endif rt = rt; /* -Wunused */ if (lt == T_BARE_WORD) { /* * Maybe check the last return code. */ if (token == T_OP_CMP_TRUE) { int isreturn; /* * Looks like a return code, treat is as such. */ isreturn = fr_str2int(modreturn_table, pleft, -1); if (isreturn != -1) { *presult = (modreturn == isreturn); return TRUE; } } /* * Bare words on the left can be attribute names. */ if (radius_get_vp(request, pleft, &vp)) { VALUE_PAIR myvp; /* * VP exists, and that's all we're looking for. */ if (token == T_OP_CMP_TRUE) { *presult = (vp != NULL); return TRUE; } if (!vp) { DICT_ATTR *da; /* * The attribute on the LHS may * have been a dynamically * registered callback. i.e. it * doesn't exist as a VALUE_PAIR. * If so, try looking for it. */ da = dict_attrbyname(pleft); 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); return TRUE; } RDEBUG2(" (Attribute %s was not found)", pleft); *presult = 0; return TRUE; } #ifdef HAVE_REGEX_H /* * Regex comparisons treat everything as * strings. */ if ((token == T_OP_REG_EQ) || (token == T_OP_REG_NE)) { vp_prints_value(buffer, sizeof(buffer), vp, 0); pleft = buffer; goto do_checks; } #endif memcpy(&myvp, vp, sizeof(myvp)); if (!pairparsevalue(&myvp, pright)) { RDEBUG2("Failed parsing \"%s\": %s", pright, fr_strerror()); return FALSE; } myvp.operator = token; *presult = paircmp(&myvp, vp); RDEBUG3(" paircmp -> %d", *presult); return TRUE; } /* else it's not a VP in a list */ } #ifdef HAVE_REGEX_H do_checks: #endif switch (token) { case T_OP_GE: case T_OP_GT: case T_OP_LE: case T_OP_LT: if (!all_digits(pright)) { RDEBUG2(" (Right field is not a number at: %s)", pright); return FALSE; } rint = strtoul(pright, NULL, 0); if (!all_digits(pleft)) { RDEBUG2(" (Left field is not a number at: %s)", pleft); return FALSE; } lint = strtoul(pleft, NULL, 0); break; default: lint = rint = 0; /* quiet the compiler */ break; } switch (token) { case T_OP_CMP_TRUE: /* * Check for truth or falsehood. */ if (all_digits(pleft)) { lint = strtoul(pleft, NULL, 0); result = (lint != 0); } else { result = (*pleft != '\0'); } break; case T_OP_CMP_EQ: result = (strcmp(pleft, pright) == 0); break; case T_OP_NE: result = (strcmp(pleft, pright) != 0); break; case T_OP_GE: result = (lint >= rint); break; case T_OP_GT: result = (lint > rint); break; case T_OP_LE: result = (lint <= rint); break; case T_OP_LT: result = (lint < rint); break; #ifdef HAVE_REGEX_H case T_OP_REG_EQ: { int i, compare; regex_t reg; regmatch_t rxmatch[REQUEST_MAX_REGEX + 1]; /* * Include substring matches. */ compare = regcomp(®, pright, cflags); if (compare != 0) { if (debug_flag) { char errbuf[128]; regerror(compare, ®, errbuf, sizeof(errbuf)); DEBUG("ERROR: Failed compiling regular expression: %s", errbuf); } return FALSE; } compare = regexec(®, pleft, REQUEST_MAX_REGEX + 1, rxmatch, 0); regfree(®); /* * Add new %{0}, %{1}, etc. */ if (compare == 0) for (i = 0; i <= REQUEST_MAX_REGEX; i++) { char *r; free(request_data_get(request, request, REQUEST_DATA_REGEX | i)); /* * No %{i}, skip it. * We MAY have %{2} without %{1}. */ if (rxmatch[i].rm_so == -1) continue; /* * Copy substring into allocated buffer */ r = rad_malloc(rxmatch[i].rm_eo -rxmatch[i].rm_so + 1); memcpy(r, pleft + rxmatch[i].rm_so, rxmatch[i].rm_eo - rxmatch[i].rm_so); r[rxmatch[i].rm_eo - rxmatch[i].rm_so] = '\0'; request_data_add(request, request, REQUEST_DATA_REGEX | i, r, free); } result = (compare == 0); } break; case T_OP_REG_NE: { int compare; regex_t reg; regmatch_t rxmatch[REQUEST_MAX_REGEX + 1]; /* * Include substring matches. */ compare = regcomp(®, pright, cflags); if (compare != 0) { if (debug_flag) { char errbuf[128]; regerror(compare, ®, errbuf, sizeof(errbuf)); DEBUG("ERROR: Failed compiling regular expression: %s", errbuf); } return FALSE; } compare = regexec(®, pleft, REQUEST_MAX_REGEX + 1, rxmatch, 0); regfree(®); result = (compare != 0); } break; #endif default: DEBUG("ERROR: Comparison operator %s is not supported", fr_token_name(token)); result = FALSE; break; } *presult = result; return TRUE; }