summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-06-27 23:03:24 +0000
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2013-06-27 23:03:24 +0000
commit8a439f8521d78dc4c3ebcca248bc60f540e83acb (patch)
treed658934a63ccd6650f91cfb0ae65b4e3832f848e
parent5b8ec508a097798e42408f3bd03ce96985cfc90e (diff)
downloadlibtdeldap-8a439f85.tar.gz
libtdeldap-8a439f85.zip
Add a number of methods to enable multi-master replication
-rw-r--r--src/libtdeldap.cpp696
-rw-r--r--src/libtdeldap.h35
2 files changed, 626 insertions, 105 deletions
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index 8209501..8aac29f 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -876,6 +876,40 @@ void add_multiple_attributes_operation(LDAPMod **mods, int *i, TQString attr, TQ
(*i)++;
}
+void delete_single_attribute_operation(LDAPMod **mods, int *i, TQString attr) {
+ mods[*i]->mod_op = LDAP_MOD_DELETE;
+ mods[*i]->mod_type = strdup(attr.ascii());
+ (*i)++;
+}
+
+void set_up_attribute_operations(LDAPMod **mods, int number_of_parameters) {
+ int i;
+ for (i=0;i<number_of_parameters;i++) {
+ mods[i] = new LDAPMod;
+ mods[i]->mod_type = NULL;
+ mods[i]->mod_values = NULL;
+ }
+ mods[number_of_parameters] = NULL;
+}
+
+void clean_up_attribute_operations(int i, LDAPMod **mods, LDAPMod *prevterm, int number_of_parameters) {
+ mods[i] = prevterm;
+ for (i=0;i<number_of_parameters;i++) {
+ if (mods[i]->mod_type != NULL) {
+ free(mods[i]->mod_type);
+ }
+ if (mods[i]->mod_values != NULL) {
+ int j = 0;
+ while (mods[i]->mod_values[j] != NULL) {
+ free(mods[i]->mod_values[j]);
+ j++;
+ }
+ free(mods[i]->mod_values);
+ }
+ delete mods[i];
+ }
+}
+
int LDAPManager::updateUserInfo(LDAPUserInfo user, TQString *errstr) {
int retcode;
int i;
@@ -889,12 +923,7 @@ int LDAPManager::updateUserInfo(LDAPUserInfo user, TQString *errstr) {
// We will replace any existing attributes with the new values
int number_of_parameters = 40; // 40 primary attributes
LDAPMod *mods[number_of_parameters+1];
- for (i=0;i<number_of_parameters;i++) {
- mods[i] = new LDAPMod;
- mods[i]->mod_type = NULL;
- mods[i]->mod_values = NULL;
- }
- mods[number_of_parameters] = NULL;
+ set_up_attribute_operations(mods, number_of_parameters);
// Load LDAP modification requests from provided data structure
i=0;
@@ -961,21 +990,7 @@ int LDAPManager::updateUserInfo(LDAPUserInfo user, TQString *errstr) {
retcode = ldap_modify_ext_s(m_ldap, user.distinguishedName.ascii(), mods, NULL, NULL);
// Clean up
- mods[i] = prevterm;
- for (i=0;i<number_of_parameters;i++) {
- if (mods[i]->mod_type != NULL) {
- free(mods[i]->mod_type);
- }
- if (mods[i]->mod_values != NULL) {
- int j = 0;
- while (mods[i]->mod_values[j] != NULL) {
- free(mods[i]->mod_values[j]);
- j++;
- }
- free(mods[i]->mod_values);
- }
- delete mods[i];
- }
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
if (retcode != LDAP_SUCCESS) {
if (errstr) {
@@ -1485,12 +1500,7 @@ int LDAPManager::updateGroupInfo(LDAPGroupInfo group, TQString *errstr) {
// We will replace any existing attributes with the new values
int number_of_parameters = 3; // 3 primary attributes
LDAPMod *mods[number_of_parameters+1];
- for (i=0;i<number_of_parameters;i++) {
- mods[i] = new LDAPMod;
- mods[i]->mod_type = NULL;
- mods[i]->mod_values = NULL;
- }
- mods[number_of_parameters] = NULL;
+ set_up_attribute_operations(mods, number_of_parameters);
// Load LDAP modification requests from provided data structure
i=0;
@@ -1520,21 +1530,7 @@ int LDAPManager::updateGroupInfo(LDAPGroupInfo group, TQString *errstr) {
retcode = ldap_modify_ext_s(m_ldap, group.distinguishedName.ascii(), mods, NULL, NULL);
// Clean up
- mods[i] = prevterm;
- for (i=0;i<number_of_parameters;i++) {
- if (mods[i]->mod_type != NULL) {
- free(mods[i]->mod_type);
- }
- if (mods[i]->mod_values != NULL) {
- int j = 0;
- while (mods[i]->mod_values[j] != NULL) {
- free(mods[i]->mod_values[j]);
- j++;
- }
- free(mods[i]->mod_values);
- }
- delete mods[i];
- }
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
if (retcode != LDAP_SUCCESS) {
if (errstr) {
@@ -1575,12 +1571,7 @@ int LDAPManager::addUserInfo(LDAPUserInfo user, TQString *errstr) {
// Create the base DN entry
int number_of_parameters = 14; // 14 primary attributes
LDAPMod *mods[number_of_parameters+1];
- for (i=0;i<number_of_parameters;i++) {
- mods[i] = new LDAPMod;
- mods[i]->mod_type = NULL;
- mods[i]->mod_values = NULL;
- }
- mods[number_of_parameters] = NULL;
+ set_up_attribute_operations(mods, number_of_parameters);
// Load initial required LDAP object attributes
i=0;
@@ -1607,21 +1598,7 @@ int LDAPManager::addUserInfo(LDAPUserInfo user, TQString *errstr) {
retcode = ldap_add_ext_s(m_ldap, user.distinguishedName.ascii(), mods, NULL, NULL);
// Clean up
- mods[i] = prevterm;
- for (i=0;i<number_of_parameters;i++) {
- if (mods[i]->mod_type != NULL) {
- free(mods[i]->mod_type);
- }
- if (mods[i]->mod_values != NULL) {
- int j = 0;
- while (mods[i]->mod_values[j] != NULL) {
- free(mods[i]->mod_values[j]);
- j++;
- }
- free(mods[i]->mod_values);
- }
- delete mods[i];
- }
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
if (retcode != LDAP_SUCCESS) {
if (errstr) {
@@ -1650,12 +1627,7 @@ int LDAPManager::addGroupInfo(LDAPGroupInfo group, TQString *errstr) {
// Create the base DN entry
int number_of_parameters = 6; // 6 primary attributes
LDAPMod *mods[number_of_parameters+1];
- for (i=0;i<number_of_parameters;i++) {
- mods[i] = new LDAPMod;
- mods[i]->mod_type = NULL;
- mods[i]->mod_values = NULL;
- }
- mods[number_of_parameters] = NULL;
+ set_up_attribute_operations(mods, number_of_parameters);
TQString placeholderGroup = "cn=placeholder," + m_basedc;
@@ -1675,21 +1647,7 @@ int LDAPManager::addGroupInfo(LDAPGroupInfo group, TQString *errstr) {
retcode = ldap_add_ext_s(m_ldap, group.distinguishedName.ascii(), mods, NULL, NULL);
// Clean up
- mods[i] = prevterm;
- for (i=0;i<number_of_parameters;i++) {
- if (mods[i]->mod_type != NULL) {
- free(mods[i]->mod_type);
- }
- if (mods[i]->mod_values != NULL) {
- int j = 0;
- while (mods[i]->mod_values[j] != NULL) {
- free(mods[i]->mod_values[j]);
- j++;
- }
- free(mods[i]->mod_values);
- }
- delete mods[i];
- }
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
if (retcode != LDAP_SUCCESS) {
if (errstr) {
@@ -2673,12 +2631,7 @@ int LDAPManager::writeCertificateFileIntoDirectory(TQByteArray cert, TQString at
// We will replace any existing attributes with the new values
int number_of_parameters = 1; // 1 primary attribute
LDAPMod *mods[number_of_parameters+1];
- for (i=0;i<number_of_parameters;i++) {
- mods[i] = new LDAPMod;
- mods[i]->mod_type = NULL;
- mods[i]->mod_values = NULL;
- }
- mods[number_of_parameters] = NULL;
+ set_up_attribute_operations(mods, number_of_parameters);
// Load LDAP modification requests from provided data structure
i=0;
@@ -2690,21 +2643,7 @@ int LDAPManager::writeCertificateFileIntoDirectory(TQByteArray cert, TQString at
retcode = ldap_modify_ext_s(m_ldap, TQString("cn=certificate store,o=tde,cn=tde realm data,ou=master services,ou=core,ou=realm,%1").arg(m_basedc).ascii(), mods, NULL, NULL);
// Clean up
- mods[i] = prevterm;
- for (i=0;i<number_of_parameters;i++) {
- if (mods[i]->mod_type != NULL) {
- free(mods[i]->mod_type);
- }
- if (mods[i]->mod_values != NULL) {
- int j = 0;
- while (mods[i]->mod_values[j] != NULL) {
- delete mods[i]->mod_values[j];
- j++;
- }
- free(mods[i]->mod_values);
- }
- delete mods[i];
- }
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
if (retcode != LDAP_SUCCESS) {
if (errstr) *errstr = i18n("<qt>LDAP certificate upload failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
@@ -2885,6 +2824,94 @@ LDAPTDEBuiltinsInfo LDAPManager::parseLDAPTDEBuiltinsRecord(LDAPMessage* entry)
return builtininfo;
}
+LDAPMasterReplicationInfo LDAPManager::parseLDAPMasterReplicationRecord(LDAPMasterReplicationInfo replicationinfo, LDAPMessage* entry) {
+ char* dn = NULL;
+ char* attr;
+ struct berval **vals;
+ BerElement* ber;
+ int i;
+
+ if((dn = ldap_get_dn(m_ldap, entry)) != NULL) {
+ ldap_memfree(dn);
+ }
+
+ for( attr = ldap_first_attribute(m_ldap, entry, &ber); attr != NULL; attr = ldap_next_attribute(m_ldap, entry, ber)) {
+ if ((vals = ldap_get_values_len(m_ldap, entry, attr)) != NULL) {
+ TQString ldap_field = attr;
+ if (ldap_field == "olcServerID") {
+ i=0;
+ while (vals[i] != NULL) {
+ TQStringList serverIDMapping = TQStringList::split(" ", TQString(vals[i]->bv_val), FALSE);
+ LDAPMasterReplicationMapping mapping;
+ mapping.id = serverIDMapping[0].toInt();
+ mapping.fqdn = serverIDMapping[1];
+ mapping.fqdn.replace("ldap:", "");
+ mapping.fqdn.replace("ldaps:", "");
+ mapping.fqdn.replace("/", "");
+ replicationinfo.serverIDs.append(mapping);
+ i++;
+ }
+ replicationinfo.informationValid = true;
+ }
+ else if (ldap_field == "olcMirrorMode") {
+ i=0;
+ TQString mirrorModeEnabled(vals[i]->bv_val);
+ if (mirrorModeEnabled == "TRUE") {
+ replicationinfo.enabled = true;
+ }
+ else {
+ replicationinfo.enabled = false;
+ }
+ }
+ ldap_value_free_len(vals);
+ }
+ ldap_memfree(attr);
+ }
+
+ if (ber != NULL) {
+ ber_free(ber, 0);
+ }
+
+ return replicationinfo;
+}
+
+TQString LDAPManager::parseLDAPSyncProvOverlayConfigRecord(LDAPMessage* entry) {
+ char* dn = NULL;
+ char* attr;
+ struct berval **vals;
+ BerElement* ber;
+ int i;
+ TQString syncProvEntry;
+
+ if((dn = ldap_get_dn(m_ldap, entry)) != NULL) {
+ ldap_memfree(dn);
+ }
+
+ for( attr = ldap_first_attribute(m_ldap, entry, &ber); attr != NULL; attr = ldap_next_attribute(m_ldap, entry, ber)) {
+ if ((vals = ldap_get_values_len(m_ldap, entry, attr)) != NULL) {
+ TQString ldap_field = attr;
+ if (ldap_field == "olcOverlay") {
+ i=0;
+ while (vals[i] != NULL) {
+ TQString value(vals[i]->bv_val);
+ if (value.endsWith("}syncprov")) {
+ syncProvEntry = value;
+ }
+ i++;
+ }
+ }
+ ldap_value_free_len(vals);
+ }
+ ldap_memfree(attr);
+ }
+
+ if (ber != NULL) {
+ ber_free(ber, 0);
+ }
+
+ return syncProvEntry;
+}
+
LDAPTDEBuiltinsInfo LDAPManager::getTDEBuiltinMappings(TQString *errstr) {
int retcode;
LDAPTDEBuiltinsInfo builtininfo;
@@ -2918,6 +2945,441 @@ LDAPTDEBuiltinsInfo LDAPManager::getTDEBuiltinMappings(TQString *errstr) {
return LDAPTDEBuiltinsInfo();
}
+LDAPMasterReplicationInfo LDAPManager::getLDAPMasterReplicationSettings(TQString *errstr) {
+ int retcode;
+ LDAPMasterReplicationInfo replicationinfo;
+
+ if (bind(errstr) < 0) {
+ return LDAPMasterReplicationInfo();
+ }
+ else {
+ // Check cn=config settings
+ LDAPMessage* msg;
+ retcode = ldap_search_ext_s(m_ldap, "cn=config", LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg);
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) *errstr = i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return LDAPMasterReplicationInfo();
+ }
+
+ // Iterate through the returned entries
+ LDAPMessage* entry;
+ for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
+ LDAPMasterReplicationInfo potentialReplicationInfo;
+ potentialReplicationInfo = parseLDAPMasterReplicationRecord(LDAPMasterReplicationInfo(), entry);
+ if (potentialReplicationInfo.informationValid) {
+ replicationinfo = potentialReplicationInfo;
+ }
+ }
+
+ // clean up
+ ldap_msgfree(msg);
+
+ // Set OpenLDAP defaults
+ replicationinfo.enabled = false;
+
+ // Check olcDatabase 0 configuration settings
+ retcode = ldap_search_ext_s(m_ldap, "olcDatabase={0}config,cn=config", LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg);
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) *errstr = i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return LDAPMasterReplicationInfo();
+ }
+
+ // Iterate through the returned entries
+ for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
+ replicationinfo = parseLDAPMasterReplicationRecord(replicationinfo, entry);
+ }
+
+ // clean up
+ ldap_msgfree(msg);
+
+ return replicationinfo;
+ }
+
+ return LDAPMasterReplicationInfo();
+}
+
+int LDAPManager::setLDAPMasterReplicationSettings(LDAPMasterReplicationInfo replicationinfo, TQString *errstr) {
+ int retcode;
+ int i;
+
+ if (bind(errstr) < 0) {
+ return -1;
+ }
+ else {
+ if (replicationinfo.enabled) {
+ if (!errstr && (replicationinfo.syncDN == "")) {
+ replicationinfo.syncDN = "cn=admin," + m_basedc;
+ }
+ if (!errstr && replicationinfo.syncPassword.isNull()) {
+ LDAPPasswordDialog passdlg(0, 0, false);
+ passdlg.m_base->ldapAdminRealm->setEnabled(false);
+ passdlg.m_base->ldapAdminRealm->insertItem(m_realm);
+ passdlg.m_base->ldapUseTLS->hide();
+ passdlg.m_base->ldapAdminUsername->setEnabled(false);
+ passdlg.m_base->ldapAdminUsername->setText(replicationinfo.syncDN);
+ if (passdlg.exec() == TQDialog::Accepted) {
+ replicationinfo.syncPassword = passdlg.m_base->ldapAdminPassword->password();
+ }
+ }
+
+ if ((replicationinfo.syncDN == "") || (replicationinfo.syncPassword.isNull())) {
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: Invalid multi-master synchronization credentials provided</qt>");
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: Invalid multi-master synchronization credentials provided</qt>"), i18n("User Error"));
+ return -1;
+ }
+
+ // Test credentials before continuing
+ LDAPCredentials* credentials = new LDAPCredentials;
+ credentials->username = replicationinfo.syncDN;
+ credentials->password = replicationinfo.syncPassword;
+ credentials->realm = m_realm;
+ LDAPManager* ldap_mgr = new LDAPManager(m_realm, "ldapi://", credentials);
+ TQString errorstring;
+ if (ldap_mgr->bind(&errorstring) != 0) {
+ delete ldap_mgr;
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: Invalid multi-master synchronization credentials provided</qt>");
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: Invalid multi-master synchronization credentials provided</qt>"), i18n("User Error"));
+ return -1;
+ }
+ delete ldap_mgr;
+ }
+
+ if (replicationinfo.serverIDs.count() <= 0) {
+ replicationinfo.enabled = false;
+ }
+
+ if (replicationinfo.serverIDs.count() > 0) {
+ // Assemble the LDAPMod structure
+ // We will replace any existing attributes with the new values
+ int number_of_parameters = 1; // 1 primary attribute
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load LDAP modification requests from provided data structure
+ i=0;
+ TQStringList serverMappingList;
+ LDAPMasterReplicationMap::iterator it;
+ for (it = replicationinfo.serverIDs.begin(); it != replicationinfo.serverIDs.end(); ++it) {
+ serverMappingList.append(TQString("%1 ldaps://%2/").arg((*it).id).arg((*it).fqdn));
+ }
+ add_multiple_attributes_operation(mods, &i, "olcServerID", serverMappingList);
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Perform LDAP update
+ retcode = ldap_modify_ext_s(m_ldap, "cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+ if (retcode == LDAP_NO_SUCH_ATTRIBUTE) {
+ // Add new object instead
+ // Assemble the LDAPMod structure
+ // We will replace any existing attributes with the new values
+ int number_of_parameters = 1; // 1 primary attribute
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load LDAP modification requests from provided data structure
+ i=0;
+ TQStringList serverMappingList;
+ LDAPMasterReplicationMap::iterator it;
+ for (it = replicationinfo.serverIDs.begin(); it != replicationinfo.serverIDs.end(); ++it) {
+ serverMappingList.append(TQString("%1 ldaps://%2/").arg((*it).id).arg((*it).fqdn));
+ }
+ create_multiple_attributes_operation(mods, &i, "olcServerID", serverMappingList);
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Perform LDAP update
+ retcode = ldap_add_ext_s(m_ldap, "cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+ }
+
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+ }
+ else {
+ // Delete the olcServerID entry
+ // Assemble the LDAPMod structure
+ int number_of_parameters = 1; // 1 primary attribute
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load LDAP delete request
+ i=0;
+ delete_single_attribute_operation(mods, &i, "olcServerID");
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Perform LDAP update
+ retcode = ldap_modify_ext_s(m_ldap, "cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+ if ((retcode != LDAP_SUCCESS) && (retcode != LDAP_NO_SUCH_ATTRIBUTE)) {
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+ }
+
+ {
+ if (replicationinfo.enabled) {
+ // Config Database
+ {
+ // Assemble the LDAPMod structure
+ // We will replace any existing attributes with the new values
+ int number_of_parameters = 2; // 2 primary attributes
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load LDAP modification requests from provided data structure
+ i=0;
+ TQStringList syncReplServerList;
+ LDAPMasterReplicationMap::iterator it;
+ int rid = 1;
+ for (it = replicationinfo.serverIDs.begin(); it != replicationinfo.serverIDs.end(); ++it) {
+ TQString ridString;
+ TQString serverSyncReplString;
+ TQString databaseDN;
+ ridString.sprintf("%03d", rid);
+ databaseDN = "cn=config";
+ serverSyncReplString = TQString("rid=%1 provider=ldaps://%2/ binddn=\"%3\" bindmethod=simple credentials=\"%4\" searchbase=\"%5\" type=refreshAndPersist retry=\"%5\" timeout=%6").arg(ridString).arg((*it).fqdn).arg(replicationinfo.syncDN).arg(replicationinfo.syncPassword).arg(databaseDN).arg(replicationinfo.retryMethod).arg(replicationinfo.timeout);
+ syncReplServerList.append(serverSyncReplString);
+ rid++;
+ }
+ add_multiple_attributes_operation(mods, &i, "olcSyncRepl", syncReplServerList);
+ add_single_attribute_operation(mods, &i, "olcMirrorMode", "TRUE");
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Perform LDAP update
+ retcode = ldap_modify_ext_s(m_ldap, "olcDatabase={0}config,cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+ }
+
+ // Main Database
+ {
+ // Assemble the LDAPMod structure
+ // We will replace any existing attributes with the new values
+ int number_of_parameters = 2; // 2 primary attributes
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load LDAP modification requests from provided data structure
+ i=0;
+ TQStringList syncReplServerList;
+ LDAPMasterReplicationMap::iterator it;
+ int rid = 1;
+ for (it = replicationinfo.serverIDs.begin(); it != replicationinfo.serverIDs.end(); ++it) {
+ TQString ridString;
+ TQString serverSyncReplString;
+ TQString databaseDN;
+ ridString.sprintf("%03d", rid);
+ databaseDN = m_basedc;
+ serverSyncReplString = TQString("rid=%1 provider=ldaps://%2/ binddn=\"%3\" bindmethod=simple credentials=\"%4\" searchbase=\"%5\" type=refreshAndPersist retry=\"%5\" timeout=%6").arg(ridString).arg((*it).fqdn).arg(replicationinfo.syncDN).arg(replicationinfo.syncPassword).arg(databaseDN).arg(replicationinfo.retryMethod).arg(replicationinfo.timeout);
+ syncReplServerList.append(serverSyncReplString);
+ rid++;
+ }
+ add_multiple_attributes_operation(mods, &i, "olcSyncRepl", syncReplServerList);
+ add_single_attribute_operation(mods, &i, "olcMirrorMode", "TRUE");
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Perform LDAP update
+ retcode = ldap_modify_ext_s(m_ldap, "olcDatabase={1}hdb,cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+ }
+ }
+ else {
+ // Delete the olcSyncRepl and olcMirrorMode entries
+
+ // Main Database
+ {
+ // Assemble the LDAPMod structure
+ int number_of_parameters = 2; // 2 primary attributes
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load LDAP delete request
+ i=0;
+ delete_single_attribute_operation(mods, &i, "olcSyncRepl");
+ delete_single_attribute_operation(mods, &i, "olcMirrorMode");
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Perform LDAP update
+ retcode = ldap_modify_ext_s(m_ldap, "olcDatabase={1}hdb,cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+ if ((retcode != LDAP_SUCCESS) && (retcode != LDAP_NO_SUCH_ATTRIBUTE)) {
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+ }
+
+ // Config Database
+ {
+ // Assemble the LDAPMod structure
+ int number_of_parameters = 2; // 2 primary attributes
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load LDAP delete request
+ i=0;
+ delete_single_attribute_operation(mods, &i, "olcSyncRepl");
+ delete_single_attribute_operation(mods, &i, "olcMirrorMode");
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Perform LDAP update
+ retcode = ldap_modify_ext_s(m_ldap, "olcDatabase={0}config,cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+ if ((retcode != LDAP_SUCCESS) && (retcode != LDAP_NO_SUCH_ATTRIBUTE)) {
+ if (errstr) *errstr = i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+ }
+ }
+
+ // Get current active replication settings
+ TQString* readOnlyErrorString = NULL;
+ LDAPMasterReplicationInfo currentReplicationInfo = getLDAPMasterReplicationSettings(readOnlyErrorString);
+ if (readOnlyErrorString) {
+ // Uh oh
+ if (errstr) *errstr = *readOnlyErrorString;
+ else KMessageBox::error(0, *readOnlyErrorString, i18n("LDAP Error"));
+ return -2;
+ }
+ if (currentReplicationInfo.enabled != replicationinfo.enabled) {
+ if (replicationinfo.enabled) {
+ // Set up replication
+ // NOTE: The syncprov module itself is already loaded by the stock TDE LDAP configuration
+
+ // Check to see if the syncprov overlay entries already exist
+ bool haveOlcOverlaySyncProv = false;
+ LDAPMessage* msg;
+ retcode = ldap_search_ext_s(m_ldap, "olcDatabase={0}config,cn=config", LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg);
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) *errstr = i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+
+ // Iterate through the returned entries
+ LDAPMessage* entry;
+ for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
+ if (parseLDAPSyncProvOverlayConfigRecord(entry) != "") {
+ haveOlcOverlaySyncProv = true;
+ }
+ }
+
+ // clean up
+ ldap_msgfree(msg);
+
+ if (!haveOlcOverlaySyncProv) {
+ // Create the base DN entry
+ int number_of_parameters = 1; // 1 primary attribute
+ LDAPMod *mods[number_of_parameters+1];
+ set_up_attribute_operations(mods, number_of_parameters);
+
+ // Load initial required LDAP object attributes
+ i=0;
+ TQStringList objectClassList;
+ objectClassList.append("olcOverlayConfig");
+ objectClassList.append("olcSyncProvConfig");
+ create_multiple_attributes_operation(mods, &i, "objectClass", objectClassList);
+ LDAPMod *prevterm = mods[i];
+ mods[i] = NULL;
+
+ // Add new object
+ retcode = ldap_add_ext_s(m_ldap, "olcOverlay=syncprov,olcDatabase={0}config,cn=config", mods, NULL, NULL);
+
+ // Clean up
+ clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) {
+ *errstr = i18n("<qt>LDAP overlay configuration failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ }
+ else {
+ KMessageBox::error(0, i18n("<qt>LDAP overlay configuration failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ }
+ return -2;
+ }
+ }
+ }
+ else {
+ // Check to see if the syncprov overlay entries exist
+ TQString olcOverlaySyncProvAttr;
+ LDAPMessage* msg;
+ retcode = ldap_search_ext_s(m_ldap, "olcDatabase={0}config,cn=config", LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg);
+ if (retcode != LDAP_SUCCESS) {
+ if (errstr) *errstr = i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+ else KMessageBox::error(0, i18n("<qt>LDAP search failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+ return -2;
+ }
+
+ // Iterate through the returned entries
+ LDAPMessage* entry;
+ for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
+ olcOverlaySyncProvAttr = parseLDAPSyncProvOverlayConfigRecord(entry);
+ if (olcOverlaySyncProvAttr != "") {
+ break;
+ }
+ }
+
+ // clean up
+ ldap_msgfree(msg);
+
+ if (olcOverlaySyncProvAttr != "") {
+ // FIXME
+ // OpenLDAP does not support removing overlays from the cn=config interface (i.e., once they are enabled above, they stay unless manually deleted from the config files)
+ // See http://www.openldap.org/lists/openldap-software/200811/msg00103.html
+ // If it were possible, the code would look something like this:
+ // retcode = ldap_delete_ext_s(m_ldap, olcOverlaySyncProvAttr + ",olcDatabase={0}config,cn=config", NULL, NULL);
+ }
+ }
+ }
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
int LDAPManager::getTDECertificate(TQString certificateName, TQString fileName, TQString *errstr) {
int retcode;
int returncode;
@@ -3774,6 +4236,30 @@ LDAPTDEBuiltinsInfo::~LDAPTDEBuiltinsInfo() {
//
}
+LDAPMasterReplicationInfo::LDAPMasterReplicationInfo() {
+ // TQStrings are always initialized to TQString::null, so they don't need initialization here...
+ informationValid = false;
+ enabled = false;
+ // FIXME
+ // Retry method and timeout should be user configurable
+ // See http://www.openldap.org/doc/admin24/slapdconfig.html for syntax
+ retryMethod = "5 5 300 5";
+ timeout = 1;
+}
+
+LDAPMasterReplicationInfo::~LDAPMasterReplicationInfo() {
+ //
+}
+
+
+LDAPMasterReplicationMapping::LDAPMasterReplicationMapping() {
+ id = -1;
+}
+
+LDAPMasterReplicationMapping::~LDAPMasterReplicationMapping() {
+ //
+}
+
KerberosTicketInfo::KerberosTicketInfo() {
// TQStrings are always initialized to TQString::null, so they don't need initialization here...
informationValid = false;
diff --git a/src/libtdeldap.h b/src/libtdeldap.h
index 2c73967..ee60b94 100644
--- a/src/libtdeldap.h
+++ b/src/libtdeldap.h
@@ -374,6 +374,37 @@ class LDAPTDEBuiltinsInfo
TQString builtinStandardUserGroup;
};
+class LDAPMasterReplicationMapping
+{
+ public:
+ LDAPMasterReplicationMapping();
+ ~LDAPMasterReplicationMapping();
+
+ public:
+ int id;
+ TQString fqdn;
+};
+
+typedef TQValueList<LDAPMasterReplicationMapping> LDAPMasterReplicationMap;
+
+class LDAPMasterReplicationInfo
+{
+ public:
+ LDAPMasterReplicationInfo();
+ ~LDAPMasterReplicationInfo();
+
+ public:
+ bool informationValid;
+ bool enabled;
+ LDAPMasterReplicationMap serverIDs;
+ TQString retryMethod;
+ int timeout;
+ int syncMethod;
+ TQString syncDN;
+ TQCString syncPassword;
+ TQString certificateFile;
+};
+
class KerberosTicketInfo
{
public:
@@ -446,6 +477,8 @@ class LDAPManager : public TQObject {
int writeCertificateFileIntoDirectory(TQByteArray cert, TQString attr, TQString* errstr=0);
LDAPTDEBuiltinsInfo getTDEBuiltinMappings(TQString *errstr=0);
+ LDAPMasterReplicationInfo getLDAPMasterReplicationSettings(TQString *errstr=0);
+ int setLDAPMasterReplicationSettings(LDAPMasterReplicationInfo replicationinfo, TQString *errstr=0);
int writeSudoersConfFile(TQString *errstr=0);
int getTDECertificate(TQString certificateName, TQString fileName, TQString *errstr=0);
int setPasswordForUser(LDAPUserInfo user, TQString *errstr);
@@ -489,6 +522,8 @@ class LDAPManager : public TQObject {
LDAPMachineInfo parseLDAPMachineRecord(LDAPMessage* entry);
LDAPServiceInfo parseLDAPMachineServiceRecord(LDAPMessage* entry);
LDAPTDEBuiltinsInfo parseLDAPTDEBuiltinsRecord(LDAPMessage* entry);
+ LDAPMasterReplicationInfo parseLDAPMasterReplicationRecord(LDAPMasterReplicationInfo replicationinfo, LDAPMessage* entry);
+ TQString parseLDAPSyncProvOverlayConfigRecord(LDAPMessage* entry);
private:
TQString m_realm;