mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-28 01:41:14 -06:00
fcb9854dcb
trigger topology updaet if suffix entry is added trigger topology update if managedSuffix is modified in host entry Reviewed-by: Simo Sorce <simo@redhat.com> Reviewed-By: Jan Cholasta <jcholast@redhat.com>
316 lines
10 KiB
C
316 lines
10 KiB
C
#include "topology.h"
|
|
|
|
/* generate the dn for a topology segment by providing replroot and segment name */
|
|
char *
|
|
ipa_topo_segment_dn(TopoReplica *tconf, char *segname)
|
|
{
|
|
char *dn = NULL;
|
|
|
|
dn = slapi_ch_smprintf("cn=%s,%s", segname, tconf->shared_config_base);
|
|
return dn;
|
|
}
|
|
|
|
/* generate the rdn for a replication agreement by providing connected nodes */
|
|
char *
|
|
ipa_topo_agmt_gen_rdn(char *from, char *to)
|
|
{
|
|
char *agmt_rdn = slapi_ch_smprintf("cn=%s-to-%s", from, to);
|
|
|
|
return agmt_rdn;
|
|
}
|
|
|
|
/* generate the rdn for a replication agreement by providing target node */
|
|
char *
|
|
ipa_topo_agmt_std_rdn(char *to)
|
|
{
|
|
char *agmt_rdn = slapi_ch_smprintf("cn=meTo%s", to);
|
|
|
|
return agmt_rdn;
|
|
}
|
|
|
|
/* generate the dn for a replication agreement by providing replroot and host */
|
|
char *
|
|
ipa_topo_agreement_dn(TopoReplica *conf, TopoReplicaAgmt *agmt, char *rdn)
|
|
{
|
|
char *dn;
|
|
char *filter;
|
|
Slapi_PBlock *pb;
|
|
Slapi_Entry **entries;
|
|
int ret;
|
|
|
|
pb = slapi_pblock_new();
|
|
filter = slapi_ch_smprintf("(&(objectclass=nsds5replica)(nsds5replicaroot=%s))",
|
|
conf->repl_root);
|
|
slapi_search_internal_set_pb(pb, "cn=config", LDAP_SCOPE_SUB,
|
|
filter, NULL, 0, NULL, NULL,
|
|
ipa_topo_get_plugin_id(), 0);
|
|
slapi_search_internal_pb(pb);
|
|
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
|
|
if (ret != 0) {
|
|
dn = NULL;
|
|
} else {
|
|
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
|
if (NULL == entries || NULL == entries[0]) {
|
|
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_agreement_dn: no replica found\n");
|
|
dn = NULL;
|
|
} else if (rdn) {
|
|
dn = slapi_ch_smprintf("%s,%s", rdn,
|
|
slapi_entry_get_dn_const(entries[0]));
|
|
} else {
|
|
dn = slapi_ch_smprintf("cn=meTo%s,%s", agmt->target,
|
|
slapi_entry_get_dn_const(entries[0]));
|
|
}
|
|
}
|
|
slapi_free_search_results_internal(pb);
|
|
slapi_pblock_destroy(pb);
|
|
return dn;
|
|
}
|
|
int
|
|
ipa_topo_agmt_new(char *hostname, TopoReplica *conf, TopoReplicaAgmt *agmt)
|
|
{
|
|
int ret = 0;
|
|
if ((agmt->repl_bind_method == NULL) /* use GSSAPI as default */ ||
|
|
(strcasecmp(agmt->repl_bind_method,"SASL/GSSAPI") == 0)) {
|
|
ret = ipa_topo_agmt_setup(hostname, conf, agmt, 1);
|
|
} else {
|
|
ret = ipa_topo_agmt_setup(hostname, conf, agmt, 0);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ipa_topo_agmt_mod(TopoReplica *conf, TopoReplicaAgmt *agmt, LDAPMod **mods,
|
|
char *direction)
|
|
{
|
|
int ret;
|
|
Slapi_PBlock *pb;
|
|
char *dn = NULL;
|
|
Slapi_Entry **entries;
|
|
int i;
|
|
LDAPMod *tmp;
|
|
Slapi_Mods *smods = NULL;
|
|
|
|
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
|
if (dn == NULL)
|
|
return 1;
|
|
|
|
pb = slapi_pblock_new();
|
|
slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_BASE,
|
|
"objectclass=*", NULL, 0, NULL, NULL,
|
|
ipa_topo_get_plugin_id(), 0);
|
|
slapi_search_internal_pb(pb);
|
|
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
|
|
if (ret != 0) {
|
|
/* search failed */
|
|
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_agmt_mod: agreement not found: %s\n", dn);
|
|
goto done;
|
|
}
|
|
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
|
if (NULL == entries || NULL == entries[0]) {
|
|
/* no entry */
|
|
ret = 1;
|
|
goto done;
|
|
}
|
|
/* apply mods to entry */
|
|
|
|
smods = slapi_mods_new();
|
|
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
|
|
char *type = ipa_topo_agmt_attr_is_managed(mods[i]->mod_type,direction);
|
|
if (type) {
|
|
tmp = mods[i];
|
|
switch (tmp->mod_op & ~LDAP_MOD_BVALUES) {
|
|
case LDAP_MOD_DELETE:
|
|
break;
|
|
case LDAP_MOD_ADD:
|
|
case LDAP_MOD_REPLACE:
|
|
slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE,
|
|
type, tmp->mod_bvalues);
|
|
break;
|
|
}
|
|
slapi_ch_free_string(&type);
|
|
}
|
|
}
|
|
if (slapi_mods_get_num_mods(smods) > 0) {
|
|
Slapi_DN *sdn = slapi_sdn_new_normdn_byref(dn);
|
|
ipa_topo_util_modify(sdn, smods);
|
|
slapi_sdn_free(&sdn);
|
|
} else {
|
|
slapi_ch_free_string(&dn);
|
|
}
|
|
slapi_mods_free(&smods);
|
|
done:
|
|
if (ret) slapi_ch_free_string(&dn);
|
|
slapi_free_search_results_internal(pb);
|
|
slapi_pblock_destroy(pb);
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
ipa_topo_agmt_del(char *hostname, TopoReplica *conf, TopoReplicaAgmt *agmt)
|
|
{
|
|
char *dn = NULL;
|
|
int rc;
|
|
|
|
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
|
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
|
"ipa_topo_agmt_del: %s\n", agmt->rdn?agmt->rdn:"RDN missing");
|
|
if (dn == NULL)
|
|
return (-1);
|
|
|
|
rc = ipa_topo_agmt_del_dn(dn);
|
|
slapi_ch_free_string(&dn);
|
|
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
ipa_topo_agmt_del_dn(char *dn)
|
|
{
|
|
int ret = 0;
|
|
Slapi_PBlock *pb;
|
|
pb = slapi_pblock_new();
|
|
slapi_delete_internal_set_pb(pb, dn, NULL, NULL,
|
|
ipa_topo_get_plugin_id(), 0);
|
|
|
|
slapi_delete_internal_pb(pb);
|
|
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
|
|
slapi_pblock_destroy(pb);
|
|
|
|
return ret;
|
|
}
|
|
int
|
|
ipa_topo_agmt_setup(char *hostname, TopoReplica *conf,
|
|
TopoReplicaAgmt *agmt, int isgssapi)
|
|
{
|
|
Slapi_Entry *e = NULL;
|
|
Slapi_PBlock *pb;
|
|
char *dn = NULL;
|
|
Slapi_DN *sdn = NULL;
|
|
char *cn;
|
|
char port[] = "389";
|
|
char *description;
|
|
int ret;
|
|
/* Set up the new replication agreement entry */
|
|
agmt->rdn = ipa_topo_agmt_gen_rdn(agmt->origin, agmt->target);
|
|
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
|
if (dn == NULL)
|
|
return -1;
|
|
sdn = slapi_sdn_new_normdn_byref(dn);
|
|
e = slapi_entry_alloc();
|
|
/* the entry now owns the dup'd dn */
|
|
slapi_entry_init_ext(e, sdn, NULL); /* sdn is copied into e */
|
|
slapi_sdn_free(&sdn);
|
|
|
|
slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, "nsds5replicationagreement");
|
|
slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, "ipaReplTopoManagedAgreement");
|
|
cn = slapi_ch_smprintf("%s-to-%s", agmt->origin, agmt->target);
|
|
slapi_entry_add_string(e, "cn",cn);
|
|
slapi_ch_free_string(&cn);
|
|
slapi_entry_add_string(e, "nsds5replicahost",hostname);
|
|
slapi_entry_add_string(e, "nsds5replicaport",port);
|
|
slapi_entry_add_string(e, "nsds5replicatimeout",AGMT_TIMEOUT);
|
|
slapi_entry_add_string(e, "nsds5replicaroot",agmt->repl_root);
|
|
description = slapi_ch_smprintf("%s to %s", ipa_topo_get_plugin_hostname(), hostname);
|
|
slapi_entry_add_string(e, "description",description);
|
|
slapi_ch_free_string(&description);
|
|
slapi_entry_add_string(e, "ipaReplTopoManagedAgreementState",
|
|
"managed agreement - generated by topology plugin");
|
|
|
|
if (isgssapi) {
|
|
slapi_entry_add_string(e, "nsds5replicatransportinfo","LDAP");
|
|
slapi_entry_add_string(e, "nsds5replicabindmethod","SASL/GSSAPI");
|
|
} else {
|
|
slapi_entry_add_string(e, "nsds5replicabinddn",REPL_MAN_DN);
|
|
slapi_entry_add_string(e, "nsds5replicacredentials",REPL_MAN_PASSWD);
|
|
slapi_entry_add_string(e, "nsds5replicatransportinfo","TLS");
|
|
slapi_entry_add_string(e, "nsds5replicabindmethod","simple");
|
|
}
|
|
if (agmt->repl_attrs) {
|
|
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeList",agmt->repl_attrs);
|
|
} else if (conf->repl_attrs) {
|
|
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeList",conf->repl_attrs);
|
|
}
|
|
if (agmt->strip_attrs) {
|
|
slapi_entry_add_string(e, "nsds5ReplicaStripAttrs", agmt->strip_attrs);
|
|
} else if (conf->strip_attrs) {
|
|
slapi_entry_add_string(e, "nsds5ReplicaStripAttrs", conf->strip_attrs);
|
|
}
|
|
if (agmt->total_attrs) {
|
|
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeListTotal",
|
|
agmt->total_attrs);
|
|
} else if (conf->total_attrs) {
|
|
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeListTotal",
|
|
conf->total_attrs);
|
|
}
|
|
|
|
pb = slapi_pblock_new();
|
|
slapi_pblock_init(pb);
|
|
|
|
/* e will be consumed by slapi_add_internal() */
|
|
slapi_add_entry_internal_set_pb(pb, e, NULL, ipa_topo_get_plugin_id(), 0);
|
|
slapi_add_internal_pb(pb);
|
|
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
|
|
slapi_pblock_destroy(pb);
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int
|
|
ipa_topo_agmt_initialize_replication(char *hostname,
|
|
TopoReplica *conf, TopoReplicaAgmt *agmt)
|
|
{
|
|
int ret = 0;
|
|
char *dn;
|
|
Slapi_Mods *smods = slapi_mods_new();
|
|
|
|
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
|
"nsds5ReplicaEnabled", "on");
|
|
slapi_mods_add_string(smods, LDAP_MOD_ADD,
|
|
"nsds5BeginReplicaRefresh", "start");
|
|
if (slapi_mods_get_num_mods(smods) > 0) {
|
|
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
|
Slapi_DN *sdn = slapi_sdn_new_normdn_byref(dn);
|
|
ipa_topo_util_modify(sdn, smods);
|
|
slapi_sdn_free(&sdn);
|
|
}
|
|
slapi_mods_free(&smods);
|
|
return ret;
|
|
}
|
|
|
|
char *
|
|
ipa_topo_agmt_attr_is_managed(char *type, char *direction)
|
|
{
|
|
char *mtype = NULL;
|
|
char **mattrs = NULL;
|
|
char *subtype;
|
|
char *ctype = slapi_ch_strdup(type);
|
|
int i;
|
|
|
|
/* segment attrs have the form
|
|
* attrtype od attrtype;direction
|
|
* find the attrtype and return the corresponding
|
|
* repl agreeement attribute type
|
|
*/
|
|
subtype = strchr(ctype,';');
|
|
if (subtype) {
|
|
/* attr is handling specific direction,
|
|
* check if interested
|
|
*/
|
|
if (strstr(ctype,direction)) {
|
|
*subtype = '\0';
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
mattrs = ipa_topo_get_plugin_managed_attrs();
|
|
for (i=0; mattrs[i]; i++) {
|
|
if(0 == strcasecmp(mattrs[i], ctype)) {
|
|
mtype = slapi_ch_strdup(mattrs[i]);
|
|
break;
|
|
}
|
|
}
|
|
return mtype;
|
|
}
|