/** Parse socket configuration * * @param[in] cs specifying the listener configuration. * @param[in] listen structure encapsulating the libldap socket. * @return * - 0 on success. * - -1 on error. */ static int proto_ldap_socket_parse(CONF_SECTION *cs, rad_listen_t *listen) { proto_ldap_inst_t *inst = listen->data; CONF_SECTION *sync_cs; size_t i; int ret; /* * Always cache the CONF_SECTION of the server. */ listen->server_cs = virtual_server_find(listen->server); if (!listen->server_cs) { cf_log_err(cs, "Failed to find virtual server '%s'", listen->server); return -1; } if (cf_section_rules_push(cs, module_config) < 0) return -1; ret = cf_section_parse(inst, inst, cs); if (ret < 0) return ret; talloc_set_type(inst, proto_ldap_inst_t); rad_assert(inst->handle_config.server_str[0]); inst->handle_config.name = talloc_typed_asprintf(inst, "proto_ldap_conn (%s)", listen->server); memcpy(&inst->handle_config.server, &inst->handle_config.server_str[0], sizeof(inst->handle_config.server)); /* * Convert scope strings to enumerated constants */ for (sync_cs = cf_section_find(cs, "sync", NULL), i = 0; sync_cs; sync_cs = cf_section_find_next(cs, sync_cs, "sync", NULL), i++) { int scope; void **tmp; CONF_SECTION *map_cs; talloc_set_type(inst->sync_config[i], sync_config_t); scope = fr_str2int(fr_ldap_scope, inst->sync_config[i]->scope_str, -1); if (scope < 0) { #ifdef LDAP_SCOPE_CHILDREN cf_log_err(cs, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" ", 'base' or 'children'", inst->sync_config[i]->scope_str); #else cf_log_err(cs, "Invalid 'user.scope' value \"%s\", expected 'sub', 'one'" " or 'base'", inst->sync_config[i]->scope_str) #endif return -1; } inst->sync_config[i]->scope = scope; /* * Needs to be NULL terminated as that's what libldap needs */ if (inst->sync_config[i]->attrs) { memcpy(&tmp, &inst->sync_config[i]->attrs, sizeof(tmp)); tmp = talloc_array_null_terminate(tmp); memcpy(&inst->sync_config[i]->attrs, tmp, sizeof(inst->sync_config[i]->attrs)); } inst->sync_config[i]->persist = true; inst->sync_config[i]->user_ctx = listen; inst->sync_config[i]->cookie = _proto_ldap_cookie_store; inst->sync_config[i]->entry = _proto_ldap_entry; inst->sync_config[i]->refresh_required = _proto_ldap_refresh_required; inst->sync_config[i]->present = _proto_ldap_present; /* * Parse and validate any maps */ map_cs = cf_section_find(sync_cs, "update", NULL); if (map_cs && map_afrom_cs(inst, &inst->sync_config[i]->entry_map, map_cs, NULL, NULL, fr_ldap_map_verify, NULL, LDAP_MAX_ATTRMAP) < 0) { return -1; } }
/** Allocate a #CONF_SECTION * * @param[in] ctx to allocate * @param[in] parent #CONF_SECTION to hang this #CONF_SECTION off of. * If parent is not NULL, the new section will be added as a child. * @param[in] name1 Primary name. * @param[in] name2 Secondary name. * @param[in] filename Caller file name for debugging. May be overridden later. * @param[in] lineno Caller line number for debugging. May be overridden later. * @return * - NULL on error. * - A new #CONF_SECTION parented by parent. */ CONF_SECTION *_cf_section_alloc(TALLOC_CTX *ctx, CONF_SECTION *parent, char const *name1, char const *name2, char const *filename, int lineno) { CONF_SECTION *cs; char buffer[1024]; if (!name1) return NULL; if (name2 && parent) { char const *p; p = strchr(name2, '$'); if (p && (p[1] != '{')) p = NULL; if (p) { name2 = cf_expand_variables(parent->item.filename, &parent->item.lineno, parent, buffer, sizeof(buffer), name2, NULL); if (!name2) { ERROR("Failed expanding section name"); return NULL; } } } cs = talloc_zero(ctx, CONF_SECTION); if (!cs) return NULL; cs->item.type = CONF_ITEM_SECTION; cs->item.parent = cf_section_to_item(parent); fr_cursor_init(&cs->item.cursor, &cs->item.child); MEM(cs->name1 = talloc_typed_strdup(cs, name1)); if (name2) { MEM(cs->name2 = talloc_typed_strdup(cs, name2)); cs->name2_quote = T_BARE_WORD; } talloc_set_destructor(cs, _cf_section_free); if (filename) cf_filename_set(cs, filename); if (lineno) cf_lineno_set(cs, lineno); if (parent) { CONF_DATA const *cd; CONF_PARSER *rule; cs->depth = parent->depth + 1; cf_item_add(parent, &(cs->item)); cd = cf_data_find(CF_TO_ITEM(parent), CONF_PARSER, cf_section_name1(parent)); if (cd) { rule = cf_data_value(cd); /* * The parent has an ON_READ rule. Check * if that rule has a child which matches * this section. */ if ((FR_BASE_TYPE(rule->type) == FR_TYPE_SUBSECTION) && ((rule->type & FR_TYPE_ON_READ) != 0) && rule->subcs) { CONF_PARSER const *rule_p; for (rule_p = rule->subcs; rule_p->name; rule_p++) { if ((FR_BASE_TYPE(rule_p->type) == FR_TYPE_SUBSECTION) && ((rule_p->type & FR_TYPE_ON_READ) != 0) && (strcmp(rule_p->name, name1) == 0)) { (void) _cf_section_rule_push(cs, rule_p, cd->item.filename, cd->item.lineno); (void) rule_p->func(ctx, NULL, NULL, cf_section_to_item(cs), rule_p); return cs; } } } } /* * Call any ON_READ callback. And push this rule * to the child section, so that the child can * pick it up. */ cd = cf_data_find(CF_TO_ITEM(parent), CONF_PARSER, name1); if (cd) { rule = cf_data_value(cd); if (rule->func && (FR_BASE_TYPE(rule->type) == FR_TYPE_SUBSECTION) && ((rule->type & FR_TYPE_ON_READ) != 0)) { (void) cf_section_rules_push(cs, rule); (void) rule->func(ctx, NULL, NULL, cf_section_to_item(cs), rule); } } } return cs; }