/** 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;
		}
	}
Exemple #2
0
/** 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;
}