* @param[in] inst rlm_ldap configuration.
* @return -1 on error else 0.
*/
-int rlm_ldap_load_clients(ldap_instance_t const *inst)
+int rlm_ldap_load_clients(ldap_instance_t const *inst, CONF_SECTION *cs)
{
- int ret = 0;
- ldap_rcode_t status;
- ldap_handle_t *conn = NULL;
+ int ret = 0;
+ ldap_rcode_t status;
+ ldap_handle_t *conn = NULL;
- /* This needs to be updated if additional attributes need to be retrieved */
- char const *attrs[7];
- char const **attrs_p;
+ char const **attrs = NULL;
+ char const **attrs_p;
- LDAPMessage *result = NULL;
- LDAPMessage *entry;
+ CONF_ITEM *ci;
+ CONF_PAIR *cp;
+ int count = 1; /* +1 for NULL termination */
- RADCLIENT *c;
+ LDAPMessage *result = NULL;
+ LDAPMessage *entry;
+
+ RADCLIENT *c;
LDAP_DBG("Loading dynamic clients");
rad_assert(inst->clientobj_base_dn);
- /*
- * Basic sanity checks.
- */
- if (!inst->clientobj_identifier) {
- LDAP_ERR("Told to load clients but 'client.identifier_attribute' not specified");
-
- return -1;
- }
-
- if (!inst->clientobj_secret) {
- LDAP_ERR("Told to load clients but 'client.secret_attribute' not specified");
-
- return -1;
- }
-
if (!inst->clientobj_filter) {
LDAP_ERR("Told to load clients but 'client.filter' not specified");
return -1;
}
- /*
- * Construct the attribute array
- */
- attrs[0] = inst->clientobj_identifier;
- attrs[1] = inst->clientobj_secret;
- attrs_p = attrs + 2;
+ for (ci = cf_item_find_next(cs, NULL);
+ ci != NULL;
+ ci = cf_item_find_next(cs, ci)) {
- if (inst->clientobj_shortname) { /* 2 */
- *attrs_p++ = inst->clientobj_shortname;
- }
+ if (!cf_item_is_pair(ci)) {
+ cf_log_err(ci, "Entry is not in \"attribute = value\" format");
+ return -1;
+ }
- if (inst->clientobj_type) { /* 3 */
- *attrs_p++ = inst->clientobj_type;
+ count++;
}
- if (inst->clientobj_server) { /* 4 */
- *attrs_p++ = inst->clientobj_server;
- }
+ /*
+ * Create an array of LDAP attributes to feed to rlm_ldap_search.
+ */
+ attrs_p = attrs = talloc_array(inst, char const *, count);
+ for (ci = cf_item_find_next(cs, NULL);
+ ci != NULL;
+ ci = cf_item_find_next(cs, ci)) {
+ char const *value;
+
+ cp = cf_itemtopair(ci);
+ value = cf_pair_value(cp);
+ if (!value) {
+ cf_log_err(ci, "Failed getting LDAP attribute name");
+ talloc_free(attrs);
+ return -1;
+ }
- if (inst->clientobj_require_ma) { /* 5 */
- *attrs_p++ = inst->clientobj_require_ma;
+ *attrs_p++ = value;
}
-
- *attrs_p = NULL; /* 6 - array needs to be NULL terminated */
+ *attrs_p = NULL;
conn = rlm_ldap_get_socket(inst, NULL);
if (!conn) return -1;
}
do {
- char *dn;
- char **identifier = NULL;
- char **shortname = NULL;
- char **secret = NULL;
- char **type = NULL;
- char **server = NULL;
- char **require_ma = NULL;
+ CONF_SECTION *cc;
+ char *dn = NULL, *id;
- dn = ldap_get_dn(conn->handle, entry);
+ char **value;
- /*
- * Check for the required attributes first
- */
- identifier = ldap_get_values(conn->handle, entry, inst->clientobj_identifier);
- if (!identifier) {
- LDAP_WARN("Client \"%s\" missing required attribute 'identifier', skipping...", dn);
- goto next;
+ id = dn = ldap_get_dn(conn->handle, entry);
+ cp = cf_pair_find(cs, "identifier");
+ if (cp) {
+ value = ldap_get_values(conn->handle, entry, cf_pair_value(cp));
+ if (value) id = value[0];
}
- secret = ldap_get_values(conn->handle, entry, inst->clientobj_secret);
- if (!secret) {
- LDAP_WARN("Client \"%s\" missing required attribute 'secret', skipping...", dn);
- goto next;
- }
+ cc = cf_section_alloc(NULL, "client", id);
- if (inst->clientobj_shortname) {
- shortname = ldap_get_values(conn->handle, entry, inst->clientobj_shortname);
- if (!shortname) {
- LDAP_DBG3("Client \"%s\" missing optional attribute 'shortname'", dn);
- }
- }
+ for (ci = cf_item_find_next(cs, NULL);
+ ci != NULL;
+ ci = cf_item_find_next(cs, ci)) {
+ char const *attr;
- if (inst->clientobj_type) {
- type = ldap_get_values(conn->handle, entry, inst->clientobj_type);
- if (!type) {
- LDAP_DBG3("Client \"%s\" missing optional attribute 'type'", dn);
- }
- }
+ cp = cf_itemtopair(ci);
+ attr = cf_pair_attr(cp);
- if (inst->clientobj_server) {
- server = ldap_get_values(conn->handle, entry, inst->clientobj_server);
- if (!server) {
- LDAP_DBG3("Client \"%s\" missing optional attribute 'server'", dn);
- }
- }
+ value = ldap_get_values(conn->handle, entry, cf_pair_value(cp));
+ if (!value) continue;
- if (inst->clientobj_require_ma) {
- require_ma = ldap_get_values(conn->handle, entry, inst->clientobj_require_ma);
- if (!require_ma) {
- LDAP_DBG3("Client \"%s\" missing optional attribute 'require_ma'", dn);
+ cp = cf_pair_alloc(cc, attr, value[0], T_OP_SET, T_SINGLE_QUOTED_STRING);
+ if (!cp) {
+ LDAP_ERR("Failed allocing pair \"%s\" = \"%s\"", attr, value[0]);
+ ret = -1;
+ goto finish;
}
+ cf_item_add(cc, cf_pairtoitem(cp));
}
- /* FIXME: We should really pass a proper ctx */
- c = client_afrom_query(NULL,
- identifier[0],
- secret[0],
- shortname ? shortname[0] : NULL,
- type ? type[0] : NULL,
- server ? server[0] : NULL,
- require_ma ? strncmp(require_ma[0], "true", 4) == 0 : false);
+ /*
+ * @todo these should be parented from something
+ */
+ c = client_afrom_cs(NULL, cc, false);
if (!c) {
- goto next;
+ talloc_free(cc);
+ ret = -1;
+ goto finish;
}
- if (!client_add(NULL, c)) {
- WARN("Failed to add client, possible duplicate?");
+ /*
+ * Client parents the CONF_SECTION which defined it
+ */
+ talloc_steal(c, cc);
+ if (!client_add(NULL, c)) {
+ LDAP_ERR("Failed to add client \"%s\", possible duplicate?", dn);
+ ret = -1;
client_free(c);
- goto next;
+ goto finish;
}
LDAP_DBG("Client \"%s\" added", dn);
- next:
ldap_memfree(dn);
- if (identifier) ldap_value_free(identifier);
- if (shortname) ldap_value_free(shortname);
- if (secret) ldap_value_free(secret);
- if (type) ldap_value_free(type);
- if (server) ldap_value_free(server);
} while ((entry = ldap_next_entry(conn->handle, entry)));
finish:
+ talloc_free(attrs);
+ if (dn) ldap_memfree(dn);
if (result) ldap_msgfree(result);
rlm_ldap_release_socket(inst, conn);
{ NULL, -1, 0, NULL, NULL }
};
-/*
- * Client configuration
- */
-static CONF_PARSER client_attribute[] = {
- { "identifier", FR_CONF_OFFSET(PW_TYPE_STRING, ldap_instance_t, clientobj_identifier), "host" },
- { "shortname", FR_CONF_OFFSET(PW_TYPE_STRING, ldap_instance_t, clientobj_shortname), "cn" },
- { "nas_type", FR_CONF_OFFSET(PW_TYPE_STRING, ldap_instance_t, clientobj_type), NULL },
- { "secret", FR_CONF_OFFSET(PW_TYPE_STRING, ldap_instance_t, clientobj_secret), NULL },
- { "virtual_server", FR_CONF_OFFSET(PW_TYPE_STRING, ldap_instance_t, clientobj_server), NULL },
- { "require_message_authenticator", FR_CONF_OFFSET(PW_TYPE_STRING, ldap_instance_t, clientobj_require_ma), NULL },
-
- { NULL, -1, 0, NULL, NULL }
-};
-
static CONF_PARSER client_config[] = {
{ "filter", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, ldap_instance_t, clientobj_filter), NULL },
{ "scope", FR_CONF_OFFSET(PW_TYPE_STRING, ldap_instance_t, clientobj_scope_str), "sub" },
{ "base_dn", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT, ldap_instance_t, clientobj_base_dn), "" },
- { "attribute", FR_CONF_POINTER(PW_TYPE_SUBSECTION, NULL), (void const *) client_attribute },
{ NULL, -1, 0, NULL, NULL }
};
if (dict_addattr(inst->cache_attribute, -1, 0, PW_TYPE_STRING, flags) < 0) {
LDAP_ERR("Error creating cache attribute: %s", fr_strerror());
- return -1;
+ goto error;
}
inst->cache_da = dict_attrbyname(inst->cache_attribute);
} else {
* Initialize the socket pool.
*/
inst->pool = fr_connection_pool_module_init(inst->cs, inst, mod_conn_create, NULL, NULL);
- if (!inst->pool) return -1;
+ if (!inst->pool) goto error;
/*
* Bulk load dynamic clients.
*/
if (inst->do_clients) {
- if (rlm_ldap_load_clients(inst) < 0) {
+ CONF_SECTION *cs;
+
+ cs = cf_section_sub_find(inst->cs, "client");
+ if (!cs) {
+ LDAP_ERR("Told to load clients but no client section found");
+ goto error;
+ }
+
+ cs = cf_section_sub_find(cs, "attribute");
+ if (!cs) {
+ LDAP_ERR("Told to load clients but no attribute section found");
+ goto error;
+ }
+
+ if (rlm_ldap_load_clients(inst, cs) < 0) {
LDAP_ERR("Error loading clients");
return -1;