From: Alan T. DeKok Date: Fri, 10 Dec 2021 19:43:44 +0000 (-0500) Subject: this has been unused for a long time X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29034e203526c36989c455e42ab6c3ff8b00f0c7;p=thirdparty%2Ffreeradius-server.git this has been unused for a long time --- diff --git a/src/lib/util/dpair_legacy.c b/src/lib/util/dpair_legacy.c deleted file mode 100644 index 97066d3738..0000000000 --- a/src/lib/util/dpair_legacy.c +++ /dev/null @@ -1,763 +0,0 @@ -/* - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -/** AVP manipulation and search API - * - * @file src/lib/util/pair.c - * - * @copyright 2000,2006,2015 The FreeRADIUS server project - */ -RCSID("$Id$") - -#include -#include -#include -#include -#include - -#include -#include - - -fr_sbuff_term_t const bareword_terminals = - FR_SBUFF_TERMS( - L("\t"), - L("\n"), - L(" "), - L("!*"), - L("!="), - L("!~"), - L("&&"), /* Logical operator */ - L(")"), /* Close condition/sub-condition */ - L("+="), - L("-="), - L(":="), - L("<"), - L("<="), - L("=*"), - L("=="), - L("=~"), - L(">"), - L(">="), - L("||"), /* Logical operator */ - ); - -/** Mark a valuepair for xlat expansion - * - * Copies xlat source (unprocessed) string to valuepair value, and sets value type. - * - * @param vp to mark for expansion. - * @param value to expand. - * @return - * - 0 if marking succeeded. - * - -1 if #fr_pair_t already had a value, or OOM. - */ -int fr_pair_mark_xlat(fr_pair_t *vp, char const *value) -{ - char *raw; - - /* - * valuepair should not already have a value. - */ - if (vp->type != VT_NONE) { - fr_strerror_const("Pair already has a value"); - return -1; - } - - raw = talloc_typed_strdup(vp, value); - if (!raw) { - fr_strerror_const("Out of memory"); - return -1; - } - - vp->type = VT_XLAT; - vp->xlat = raw; - vp->vp_length = 0; - - return 0; -} - -/** Create a valuepair from an ASCII attribute and value - * - * Where the attribute name is in the form: - * - Attr-%d - * - Attr-%d.%d.%d... - * - * @param ctx for talloc - * @param dict to user for partial resolution. - * @param attribute name to parse. - * @param value to parse (must be a hex string). - * @param op to assign to new valuepair. - * @return new #fr_pair_t or NULL on error. - */ -static fr_pair_t *fr_pair_make_unknown(TALLOC_CTX *ctx, fr_dict_t const *dict, - char const *attribute, char const *value, - fr_token_t op) -{ - fr_pair_t *vp; - fr_dict_attr_t *n; - fr_sbuff_t sbuff = FR_SBUFF_IN(attribute, strlen(attribute)); - - vp = fr_pair_alloc_null(ctx); - if (!vp) return NULL; - - if ((fr_dict_unknown_afrom_oid_substr(vp, NULL, &n, fr_dict_root(dict), &sbuff, NULL) <= 0) || - fr_sbuff_remaining(&sbuff)) { - talloc_free(vp); - return NULL; - } - vp->da = n; - - /* - * No value, but ensure that we still set up vp->data properly. - */ - if (!value) { - value = ""; - - } else if (strncasecmp(value, "0x", 2) != 0) { - /* - * Unknown attributes MUST be of type 'octets' - */ - fr_strerror_printf("Unknown attribute \"%s\" requires a hex " - "string, not \"%s\"", attribute, value); - talloc_free(vp); - return NULL; - } - - if (fr_pair_value_from_str(vp, value, strlen(value), &fr_value_unescape_double, false) < 0) { - talloc_free(vp); - return NULL; - } - - vp->op = (op == 0) ? T_OP_EQ : op; - return vp; -} - -/** Create a #fr_pair_t from ASCII strings - * - * Converts an attribute string identifier (with an optional tag qualifier) - * and value string into a #fr_pair_t. - * - * The string value is parsed according to the type of #fr_pair_t being created. - * - * @param[in] ctx for talloc. - * @param[in] dict to look attributes up in. - * @param[in] vps list where the attribute will be added (optional) - * @param[in] attribute name. - * @param[in] value attribute value (may be NULL if value will be set later). - * @param[in] op to assign to new #fr_pair_t. - * @return a new #fr_pair_t. - */ -fr_pair_t *fr_pair_make(TALLOC_CTX *ctx, fr_dict_t const *dict, fr_pair_list_t *vps, - char const *attribute, char const *value, fr_token_t op) -{ - fr_dict_attr_t const *da; - fr_pair_t *vp; - char const *attrname = attribute; - - /* - * It's not found in the dictionary, so we use - * another method to create the attribute. - */ - da = fr_dict_attr_search_by_qualified_oid(NULL, dict, attrname, true); - if (!da) { - vp = fr_pair_make_unknown(ctx, dict, attrname, value, op); - if (!vp) return NULL; - - if (vps) fr_pair_add(vps, vp); - return vp; - } - - if (da->type == FR_TYPE_GROUP) { - fr_strerror_const("Attributes of type 'group' are not supported"); - return NULL; - } - - vp = fr_pair_afrom_da(ctx, da); - if (!vp) return NULL; - vp->op = (op == 0) ? T_OP_EQ : op; - - switch (vp->op) { - case T_OP_CMP_TRUE: - case T_OP_CMP_FALSE: - fr_pair_value_clear(vp); - value = NULL; /* ignore it! */ - break; - - /* - * Regular expression comparison of integer attributes - * does a STRING comparison of the names of their - * integer attributes. - */ - case T_OP_REG_EQ: /* =~ */ - case T_OP_REG_NE: /* !~ */ - { -#ifndef HAVE_REGEX - fr_strerror_const("Regular expressions are not supported"); - return NULL; -#else - ssize_t slen; - regex_t *preg; - - /* - * Someone else will fill in the value. - */ - if (!value) break; - - talloc_free(vp); - - slen = regex_compile(ctx, &preg, value, strlen(value), NULL, false, true); - if (slen <= 0) { - fr_strerror_printf_push("Error at offset %zu compiling regex for %s", -slen, attribute); - return NULL; - } - talloc_free(preg); - - vp = fr_pair_afrom_da(ctx, da); - if (!vp) return NULL; - vp->op = op; - - if (fr_pair_mark_xlat(vp, value) < 0) { - talloc_free(vp); - return NULL; - } - - value = NULL; /* ignore it */ - break; -#endif - } - default: - break; - } - - /* - * We probably want to fix fr_pair_value_from_str to accept - * octets as values for any attribute. - */ - if (value && (fr_pair_value_from_str(vp, value, strlen(value), &fr_value_unescape_double, true) < 0)) { - talloc_free(vp); - return NULL; - } - - if (vps) fr_pair_add(vps, vp); - return vp; -} - -/** Read one line of attribute/value pairs into a list. - * - * The line may specify multiple attributes separated by commas. - * - * @note If the function returns #T_INVALID, an error has occurred and - * @note the valuepair list should probably be freed. - * - * @param[in] ctx for talloc - * @param[in] parent parent to start referencing from - * @param[in] buffer to read valuepairs from. - * @param[in] list where the parsed fr_pair_ts will be appended. - * @param[in,out] token The last token we parsed - * @param[in] depth the nesting depth for FR_TYPE_GROUP - * @return - * - <= 0 on failure. - * - The number of bytes of name consumed on success. - */ -static ssize_t fr_pair_list_afrom_substr(TALLOC_CTX *ctx, fr_dict_attr_t const *parent, char const *buffer, - fr_pair_list_t *list, fr_token_t *token, int depth) -{ - fr_pair_list_t tmp_list; - fr_pair_t *vp; - char const *p, *next; - fr_token_t last_token = T_INVALID; - fr_pair_t_RAW raw; - fr_dict_attr_t const *internal = fr_dict_root(fr_dict_internal()); - - if (internal == parent) internal = NULL; - - /* - * We allow an empty line. - */ - if (buffer[0] == 0) { - *token = T_EOL; - return 0; - } - - fr_pair_list_init(&tmp_list); - - p = buffer; - while (true) { - ssize_t slen; - fr_dict_attr_t const *da; - fr_dict_attr_t *da_unknown = NULL; - fr_skip_whitespace(p); - - /* - * Stop at the end of the input, returning - * whatever token was last read. - */ - if (!*p) break; - - if (*p == '#') { - last_token = T_EOL; - break; - } - - /* - * Hacky hack... - */ - if (strncmp(p, "raw.", 4) == 0) goto do_unknown; - - /* - * Parse the name. - */ - slen = fr_dict_attr_by_oid_substr(NULL, &da, parent, - &FR_SBUFF_IN(p, strlen(p)), &bareword_terminals); - if ((slen <= 0) && internal) { - slen = fr_dict_attr_by_oid_substr(NULL, &da, internal, - &FR_SBUFF_IN(p, strlen(p)), &bareword_terminals); - } - if (slen <= 0) { - do_unknown: - slen = fr_dict_unknown_afrom_oid_substr(ctx, NULL, &da_unknown, parent, - &FR_SBUFF_IN(p, strlen(p)), &bareword_terminals); - if (slen <= 0) { - p += -slen; - - error: - fr_pair_list_free(&tmp_list); - *token = T_INVALID; - return -(p - buffer); - } - - da = da_unknown; - } - - next = p + slen; - - if ((size_t) (next - p) >= sizeof(raw.l_opand)) { - fr_dict_unknown_free(&da); - fr_strerror_const("Attribute name too long"); - goto error; - } - - memcpy(raw.l_opand, p, next - p); - raw.l_opand[next - p] = '\0'; - raw.r_opand[0] = '\0'; - - p = next; - fr_skip_whitespace(p); - - /* - * There must be an operator here. - */ - raw.op = gettoken(&p, raw.r_opand, sizeof(raw.r_opand), false); - if ((raw.op < T_EQSTART) || (raw.op > T_EQEND)) { - fr_dict_unknown_free(&da); - fr_strerror_const("Expecting operator"); - goto error; - } - - fr_skip_whitespace(p); - - /* - * Allow grouping attributes. - */ - if ((da->type == FR_TYPE_GROUP) || (da->type == FR_TYPE_TLV) || (da->type == FR_TYPE_STRUCT)) { - if (*p != '{') { - fr_strerror_printf("Group list for %s MUST start with '{'", da->name); - goto error; - } - p++; - - vp = fr_pair_afrom_da(ctx, da); - if (!vp) goto error; - - /* - * Find the new root attribute to start encoding from. - */ - parent = fr_dict_attr_ref(da); - if (!parent) parent = da; - - slen = fr_pair_list_afrom_substr(vp, parent, p, &vp->vp_group, &last_token, depth + 1); - if (slen <= 0) { - talloc_free(vp); - goto error; - } - - if (last_token != T_RCBRACE) { - failed_group: - fr_strerror_const("Failed to end group list with '}'"); - talloc_free(vp); - goto error; - } - - p += slen; - fr_skip_whitespace(p); - if (*p != '}') goto failed_group; - p++; - - } else { - fr_token_t quote; - char const *q; - - /* - * Get the RHS thing. - */ - quote = gettoken(&p, raw.r_opand, sizeof(raw.r_opand), false); - if (quote == T_EOL) { - fr_strerror_const("Failed to get value"); - goto error; - } - - switch (quote) { - /* - * Perhaps do xlat's - */ - case T_DOUBLE_QUOTED_STRING: - /* - * Only report as double quoted if it contained valid - * a valid xlat expansion. - */ - q = strchr(raw.r_opand, '%'); - if (q && (q[1] == '{')) { - raw.quote = quote; - } else { - raw.quote = T_SINGLE_QUOTED_STRING; - } - break; - - case T_SINGLE_QUOTED_STRING: - case T_BACK_QUOTED_STRING: - case T_BARE_WORD: - raw.quote = quote; - break; - - default: - fr_strerror_printf("Failed to find expected value on right hand side in %s", da->name); - goto error; - } - - fr_skip_whitespace(p); - - /* - * Regular expressions get sanity checked by pair_make(). - * - * @todo - note that they will also be escaped, - * so we may need to fix that later. - */ - if ((raw.op == T_OP_REG_EQ) || (raw.op == T_OP_REG_NE)) { - vp = fr_pair_afrom_da(ctx, da); - if (!vp) goto error; - vp->op = raw.op; - - fr_pair_value_bstrndup(vp, raw.r_opand, strlen(raw.r_opand), false); - } else { - /* - * All other attributes get the name - * parsed. - */ - vp = fr_pair_afrom_da(ctx, da); - if (!vp) goto error; - vp->op = raw.op; - - /* - * We don't care what the value is, so - * ignore it. - */ - if ((raw.op == T_OP_CMP_TRUE) || (raw.op == T_OP_CMP_FALSE)) goto next; - - /* - * fr_pair_raw_from_str() only returns this when - * the input looks like it needs to be xlat'd. - */ - if (raw.quote == T_DOUBLE_QUOTED_STRING) { - if (fr_pair_mark_xlat(vp, raw.r_opand) < 0) { - talloc_free(vp); - goto error; - } - - /* - * Parse it ourselves. The RHS - * might NOT be tainted, but we - * don't know. So just mark it - * as such to be safe. - */ - } else if (fr_pair_value_from_str(vp, raw.r_opand, strlen(raw.r_opand), - fr_value_unescape_by_quote[raw.quote], true) < 0) { - talloc_free(vp); - goto error; - } - } - } - - next: - /* - * Free the unknown attribute, we don't need it any more. - */ - fr_dict_unknown_free(&da); - - fr_pair_add(&tmp_list, vp); - - /* - * Now look for EOL, hash, etc. - */ - if (!*p || (*p == '#') || (*p == '\n')) { - last_token = T_EOL; - break; - } - - /* - * Check for nested groups. - */ - if ((depth > 0) && (p[0] == ' ') && (p[1] == '}')) p++; - - /* - * Stop at '}', too, if we're inside of a group. - */ - if ((depth > 0) && (*p == '}')) { - last_token = T_RCBRACE; - break; - } - - if (*p != ',') { - fr_strerror_printf("Expected ',', got '%c' at offset %zu", *p, p - buffer); - goto error; - } - p++; - last_token = T_COMMA; - } - - if (!fr_pair_list_empty(&tmp_list)) fr_tmp_pair_list_move(list, &tmp_list); - - /* - * And return the last token which we read. - */ - *token = last_token; - return p - buffer; -} - -/** Read one line of attribute/value pairs into a list. - * - * The line may specify multiple attributes separated by commas. - * - * @note If the function returns #T_INVALID, an error has occurred and - * @note the valuepair list should probably be freed. - * - * @param[in] ctx for talloc - * @param[in] dict to resolve attributes in. - * @param[in] buffer to read valuepairs from. - * @param[in] list where the parsed fr_pair_ts will be appended. - * @return the last token parsed, or #T_INVALID - */ -fr_token_t fr_pair_list_afrom_str(TALLOC_CTX *ctx, fr_dict_t const *dict, char const *buffer, fr_pair_list_t *list) -{ - fr_token_t token; - - (void) fr_pair_list_afrom_substr(ctx, fr_dict_root(dict), buffer, list, &token, 0); - return token; -} - -/** Read valuepairs from the fp up to End-Of-File. - * - * @param[in] ctx for talloc - * @param[in] dict to resolve attributes in. - * @param[in,out] out where the parsed fr_pair_ts will be appended. - * @param[in] fp to read valuepairs from. - * @param[out] pfiledone true if file parsing complete; - * @return - * - 0 on success - * - -1 on error - */ -int fr_pair_list_afrom_file(TALLOC_CTX *ctx, fr_dict_t const *dict, fr_pair_list_t *out, FILE *fp, bool *pfiledone) -{ - fr_token_t last_token = T_EOL; - bool found = false; - char buf[8192]; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - fr_pair_list_t tmp_list; - - /* - * If we get a '\n' by itself, we assume that's - * the end of that VP list. - */ - if (buf[0] == '\n') { - if (found) { - *pfiledone = false; - return 0; - } - continue; - } - - /* - * Comments get ignored - */ - if (buf[0] == '#') continue; - - /* - * Read all of the attributes on the current line. - * - * If we get nothing but an EOL, it's likely OK. - */ - fr_pair_list_init(&tmp_list); - last_token = fr_pair_list_afrom_str(ctx, dict, buf, &tmp_list); - if (fr_dlist_empty(&tmp_list.head)) { - if (last_token == T_EOL) break; - - /* - * Didn't read anything, but the previous - * line wasn't EOL. The input file has a - * format error. - */ - *pfiledone = false; - fr_pair_list_free(out); - return -1; - } - - found = true; - fr_tmp_pair_list_move(out, &tmp_list); - } - - *pfiledone = true; - return 0; -} - - -/** Move pairs from source list to destination list respecting operator - * - * @note This function does some additional magic that's probably not needed - * in most places. Consider using radius_pairmove in server code. - * - * @note fr_pair_list_free should be called on the head of the source list to free - * unmoved attributes (if they're no longer needed). - * - * @param[in,out] to destination list. - * @param[in,out] from source list. - * - * @see radius_pairmove - */ -void fr_pair_list_move_op(fr_pair_list_t *to, fr_pair_list_t *from, fr_token_t op) -{ - fr_pair_t *i, *found; - fr_pair_list_t head_new, head_prepend; - - if (!to || fr_pair_list_empty(from)) return; - - /* - * We're editing the "to" list while we're adding new - * attributes to it. We don't want the new attributes to - * be edited, so we create an intermediate list to hold - * them during the editing process. - */ - fr_pair_list_init(&head_new); - fr_pair_list_init(&head_prepend); - - /* - * We're looping over the "from" list, moving some - * attributes out, but leaving others in place. - */ - for (i = fr_pair_list_head(from); i; ) { - fr_pair_t *j; - - PAIR_VERIFY(i); - - /* - * We never move Fall-Through. - */ - if (fr_dict_attr_is_top_level(i->da) && (i->da->attr == FR_FALL_THROUGH)) { - i = fr_pair_list_next(from, i); - continue; - } - - /* - * Unlike previous versions, we treat all other - * attributes as normal. i.e. there's no special - * treatment for passwords or Hint. - */ - - switch (i->op) { - /* - * Anything else are operators which - * shouldn't occur. We ignore them, and - * leave them in place. - */ - default: - i = fr_pair_list_next(from, i); - continue; - - /* - * Add it to the "to" list, but only if - * it doesn't already exist. - */ - case T_OP_EQ: - found = fr_pair_find_by_da_idx(to, i->da); - if (!found) goto do_add; - - i = fr_pair_list_next(from, i); - continue; - - /* - * Add it to the "to" list, and delete any attribute - * of the same vendor/attr which already exists. - */ - case T_OP_SET: - found = fr_pair_find_by_da_idx(to, i->da); - if (!found) goto do_add; - - /* - * Delete *all* of the attributes - * of the same number. - */ - fr_pair_delete_by_da(to, found->da); - goto do_add; - - /* - * Move it from the old list and add it - * to the new list. - */ - case T_OP_ADD_EQ: - do_add: - j = fr_pair_list_next(from, i); - fr_pair_remove(from, i); - fr_pair_add(&head_new, i); - i = j; - continue; - case T_OP_PREPEND: - j = fr_pair_list_next(from, i); - fr_pair_remove(from, i); - fr_pair_prepend(&head_prepend, i); - i = j; - continue; - } - } /* loop over the "from" list. */ - - /* - * If the op parameter was prepend add the "new" list - * attributes first as those whose individual operator - * is prepend should be prepended to the resulting list - */ - if (op == T_OP_PREPEND) fr_tmp_pair_list_move_head(to, &head_new); - - /* - * If there are any items in the prepend list prepend - * it to the "to" list - */ - fr_tmp_pair_list_move_head(to, &head_prepend); - - /* - * If the op parameter was not prepend, take the "new" - * list and append it to the "to" list - */ - if (op != T_OP_PREPEND) fr_tmp_pair_list_move(to, &head_new); -}