/** Iterate over all client attribute pairs and create client pair data using JSON element names * * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS as well to support nested * configurations sections. * * @param client The new client config section using the mapped names. * @param map The client attribute section from the module configuration. * @param json JSON object representation of a client document fetched from Couchbase. * @param docid Document id. * @return Returns 0 on success, -1 on error. */ int _mod_client_map_section(CONF_SECTION *client, CONF_SECTION const *map, json_object *json, char const *docid) { CONF_ITEM const *ci; for (ci = cf_item_find_next(map, NULL); ci != NULL; ci = cf_item_find_next(map, ci)) { CONF_PAIR const *cp; char const *attribute; char const *element; json_object *jval; /* * Recursively process map subsection */ if (cf_item_is_section(ci)) { CONF_SECTION *cs, *cc; /* local scoped for new section */ cs = cf_itemtosection(ci); cc = cf_section_alloc(client, cf_section_name1(cs), cf_section_name2(cs)); if (!cc) return -1; cf_section_add(client, cc); if (_mod_client_map_section(cc, cs, json, docid) != 0) { return -1; } /* continue on to the next item */ continue; } /* create pair from item and get attribute name and value */ cp = cf_itemtopair(ci); attribute = cf_pair_attr(cp); element = cf_pair_value(cp); /* attempt to find element in json object */ if (!json_object_object_get_ex(json, element, &jval)) { /* skip this item */ continue; } /* allocate config pair */ cp = cf_pair_alloc(client, attribute, json_object_get_string(jval), T_OP_SET, T_SINGLE_QUOTED_STRING); /* check pair */ if (!cp) { ERROR("rlm_couchbase: failed allocating config pair '%s' = '%s'", attribute, json_object_get_string(jval)); return -1; } /* add pair to section */ cf_item_add(client, cf_pairtoitem(cp)); } /* return success */ return 0; }
/** Allocate a fake client representing the LDAP connection * * The server expects a client, and it's easier to fake one than check all * request->client dereferences. * * @param[in] inst of proto_ldap to allocate a fake client for. * @return * - A fake client. * - NULL on error. */ static RADCLIENT *proto_ldap_fake_client_alloc(proto_ldap_inst_t *inst) { CONF_SECTION *cs; CONF_PAIR *cp; RADCLIENT *client; char buffer[FR_IPADDR_STRLEN]; cs = cf_section_alloc(NULL, NULL, "client", "ldap"); cp = cf_pair_alloc(cs, "ipaddr", fr_inet_ntop(buffer, sizeof(buffer), &inst->dst_ipaddr), T_OP_EQ, T_BARE_WORD, T_BARE_WORD); cf_pair_add(cs, cp); cp = cf_pair_alloc(cs, "secret", "fake", T_OP_EQ, T_BARE_WORD, T_BARE_WORD); cf_pair_add(cs, cp); client = client_afrom_cs(inst, cs, NULL); if (!client) { PERROR("Failed creating fake LDAP client"); talloc_free(cs); return NULL; } talloc_steal(client, cs); return client; }
/** Iterate over pairs in mapping section creating equivalent client pairs from LDAP values * * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS too. * * @param[in] inst rlm_ldap configuration. * @param[out] client config section. * @param[in] map section. * @param[in] conn LDAP connection. * @param[in] entry returned from search. * @return 0 on success else -1 on error. */ static int rlm_ldap_client_map_section(ldap_instance_t const *inst, CONF_SECTION *client, CONF_SECTION const *map, ldap_handle_t *conn, LDAPMessage *entry) { CONF_ITEM const *ci; for (ci = cf_item_find_next(map, NULL); ci != NULL; ci = cf_item_find_next(map, ci)) { CONF_PAIR const *cp; char **value; char const *attr; /* * Recursively process map subsection */ if (cf_item_is_section(ci)) { CONF_SECTION *cs, *cc; cs = cf_itemtosection(ci); cc = cf_section_alloc(client, cf_section_name1(cs), cf_section_name2(cs)); if (!cc) return -1; cf_section_add(client, cc); if (rlm_ldap_client_map_section(inst, cc, cs, conn, entry) < 0) return -1; continue; } cp = cf_itemtopair(ci); attr = cf_pair_attr(cp); value = ldap_get_values(conn->handle, entry, cf_pair_value(cp)); if (!value) continue; cp = cf_pair_alloc(client, attr, value[0], T_OP_SET, T_SINGLE_QUOTED_STRING); if (!cp) { LDAP_ERR("Failed allocing pair \"%s\" = \"%s\"", attr, value[0]); return -1; } cf_item_add(client, cf_pairtoitem(cp)); } return 0; }
/** Create a client CONF_SECTION using a mapping section to map values from a result set to client attributes * * If we hit a CONF_SECTION we recurse and process its CONF_PAIRS too. * * @note Caller should free CONF_SECTION passed in as out, on error. * Contents of that section will be in an undefined state. * * @param[in,out] out Section to perform mapping on. Either the root of the client config, or a parent section * (when this function is called recursively). * Should be alloced with cf_section_alloc, or if there's a separate template section, the * result of calling cf_section_dup on that section. * @param[in] map section. * @param[in] func to call to retrieve CONF_PAIR values. Must return a talloced buffer containing the value. * @param[in] data to pass to func, usually a result pointer. * @return 0 on success else -1 on error. */ int client_map_section(CONF_SECTION *out, CONF_SECTION const *map, client_value_cb_t func, void *data) { CONF_ITEM const *ci; for (ci = cf_item_find_next(map, NULL); ci != NULL; ci = cf_item_find_next(map, ci)) { CONF_PAIR const *cp; CONF_PAIR *old; char *value; char const *attr; /* * Recursively process map subsection */ if (cf_item_is_section(ci)) { CONF_SECTION *cs, *cc; cs = cf_item_to_section(ci); /* * Use pre-existing section or alloc a new one */ cc = cf_section_sub_find_name2(out, cf_section_name1(cs), cf_section_name2(cs)); if (!cc) { cc = cf_section_alloc(out, cf_section_name1(cs), cf_section_name2(cs)); cf_section_add(out, cc); if (!cc) return -1; } if (client_map_section(cc, cs, func, data) < 0) return -1; continue; } cp = cf_item_to_pair(ci); attr = cf_pair_attr(cp); /* * The callback can return 0 (success) and not provide a value * in which case we skip the mapping pair. * * Or return -1 in which case we error out. */ if (func(&value, cp, data) < 0) { cf_log_err_cs(out, "Failed performing mapping \"%s\" = \"%s\"", attr, cf_pair_value(cp)); return -1; } if (!value) continue; /* * Replace an existing CONF_PAIR */ old = cf_pair_find(out, attr); if (old) { cf_pair_replace(out, old, value); talloc_free(value); continue; } /* * ...or add a new CONF_PAIR */ cp = cf_pair_alloc(out, attr, value, T_OP_SET, T_BARE_WORD, T_SINGLE_QUOTED_STRING); if (!cp) { cf_log_err_cs(out, "Failed allocing pair \"%s\" = \"%s\"", attr, value); talloc_free(value); return -1; } talloc_free(value); cf_item_add(out, cf_pair_to_item(cp)); } return 0; }