/*************************************************************************** * Copyright (C) 2012 by Timothy Pearson * * kb9vqf@pearsoncomputing.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sha1.h" #include "ldapcontroller.h" #include "primaryrealmwizard/primaryrealmwizard.h" #include "secondaryrealmwizard/secondaryrealmwizard.h" #include "processingdialog.h" #include "multimasterreplicationconfigdlg.h" #include "ldapcontrollerconfigbase.h" // FIXME // Connect this to CMake/Automake #define KDE_CONFDIR "/etc/trinity" #define TDE_LIBDIR "/opt/trinity/lib" #define LDAP_KEYTAB_FILE "/etc/ldap/ldap.keytab" // FIXME // This assumes Debian! // RedHat would be "/etc/sysconfig/ldap" #define LDAP_DEFAULT_FILE "/etc/default/slapd" #define HEIMDAL_DEFAULT_FILE "/etc/default/heimdal-kdc" #define SASL_DEFAULT_FILE "/etc/default/saslauthd" #define SASL_CONTROL_FILE "/etc/ldap/sasl2/slapd.conf" #define HEIMDAL_ACL_FILE "/etc/heimdal-kdc/kadmind.acl" #define ROLE_WORKSTATION 0 #define ROLE_SECONDARY_REALM_CONTROLLER 1 #define ROLE_PRIMARY_REALM_CONTROLLER 2 #define KEY_STRENGTH 2048 typedef KGenericFactory ldapFactory; K_EXPORT_COMPONENT_FACTORY( kcm_ldapcontroller, ldapFactory("kcmldapcontroller")) LDAPController::LDAPController(TQWidget *parent, const char *name, const TQStringList&) : TDECModule(parent, name), myAboutData(0) { TQVBoxLayout *layout = new TQVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); m_systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" )); m_systemconfig->setFileWriteMode(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); TDEAboutData* about = new TDEAboutData("ldapcontroller", I18N_NOOP("TDE LDAP Controller"), "0.1", I18N_NOOP("TDE LDAP Controller Control Panel Module"), TDEAboutData::License_GPL, I18N_NOOP("(c) 2012 Timothy Pearson"), 0, 0); about->addAuthor("Timothy Pearson", 0, "kb9vqf@pearsoncomputing.net"); setAboutData( about ); m_base = new LDAPControllerConfigBase(this); layout->add(m_base); m_base->systemRole->clear(); m_base->systemRole->insertItem("Workstation", ROLE_WORKSTATION); m_base->systemRole->insertItem("Secondary Realm Controller", ROLE_SECONDARY_REALM_CONTROLLER); m_base->systemRole->insertItem("Primary Realm Controller", ROLE_PRIMARY_REALM_CONTROLLER); m_base->multiMasterReplicationMappings->setAllColumnsShowFocus(true); m_base->multiMasterReplicationMappings->setFullWidth(true); setRootOnlyMsg(i18n("LDAP controller settings take effect system wide, and require administrator access to modify
To alter the system's realm controller settings, click on the \"Administrator Mode\" button below.")); setUseRootOnlyMsg(true); connect(m_base->systemEnableSupport, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed())); connect(m_base->systemEnableSupport, TQT_SIGNAL(clicked()), this, TQT_SLOT(processLockouts())); connect(m_base->systemRole, TQT_SIGNAL(activated(const TQString&)), this, TQT_SLOT(systemRoleChanged())); connect(m_base->caSetMaster, TQT_SIGNAL(clicked()), this, TQT_SLOT(btncaSetMaster())); connect(m_base->caRegenerate, TQT_SIGNAL(clicked()), this, TQT_SLOT(btncaRegenerate())); connect(m_base->caExportKey, TQT_SIGNAL(clicked()), this, TQT_SLOT(btncaExportKey())); connect(m_base->caExportCert, TQT_SIGNAL(clicked()), this, TQT_SLOT(btncaExportCert())); connect(m_base->krbRegenerate, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnkrbRegenerate())); connect(m_base->krbExportKey, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnkrbExportKey())); connect(m_base->krbExportCert, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnkrbExportCert())); connect(m_base->ldapRegenerate, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnldapRegenerate())); connect(m_base->ldapExportKey, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnldapExportKey())); connect(m_base->ldapExportCert, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnldapExportCert())); connect(m_base->btnChangeLDAPRootPassword, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnChangeLDAPRootPassword())); connect(m_base->btnChangeRealmAdminPassword, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnChangeRealmAdminPassword())); connect(&m_certRefreshTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(updateCertDisplay())); connect(m_base->advancedEnableMultiMasterReplication, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed())); connect(m_base->btnAddMultiMasterReplicationMapping, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnAddMultiMasterReplicationMapping())); connect(m_base->btnEditMultiMasterReplicationMapping, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnEditMultiMasterReplicationMapping())); connect(m_base->btnRemoveMultiMasterReplicationMapping, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnRemoveMultiMasterReplicationMapping())); connect(m_base->multiMasterReplicationMappings, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(multiMasterReplicationHighlighted())); connect(m_base->multiMasterReplicationMappings, TQT_SIGNAL(executed(TQListViewItem*)), this, TQT_SLOT(modifySelectedMultiMasterReplication())); m_fqdn = LDAPManager::getMachineFQDN(); m_roleFullyConfigured = true; // FIXME // This assumes Debian! m_ldapUserName = "openldap"; m_ldapGroupName = "openldap"; load(); processLockouts(); }; LDAPController::~LDAPController() { } void system_safe(const char * cmdstr) { if (system(cmdstr) < 0) { printf("[ERROR] System call to '%s' failed!\n\r", cmdstr); } } void chown_safe(const char * file, uid_t user, gid_t group) { if (chown(file, user, group) < 0) { printf("[ERROR] Chown call to '%s' for %d:%d failed!\n\r", file, user, group); } } void LDAPController::systemRoleChanged() { int previousRole = m_prevRole; if (m_base->systemRole->currentItem() != m_prevRole) { // Verify that this workstation was not already bonded to an LDAP realm! bool bonded = false; TQStringList cfgRealms = m_systemconfig->groupList(); for (TQStringList::Iterator it(cfgRealms.begin()); it != cfgRealms.end(); ++it) { if ((*it).startsWith("LDAPRealm-")) { m_systemconfig->setGroup(*it); if (m_systemconfig->readBoolEntry("bonded", false) == true) { bonded = true; } } } if (m_base->systemRole->currentItem() == ROLE_PRIMARY_REALM_CONTROLLER) { if (previousRole == ROLE_SECONDARY_REALM_CONTROLLER) { // TODO FIXME KMessageBox::error(0, i18n("Secondary realm controller promotion is not yet available

If you want to see it implemented, contact the Trinity Desktop developers"), i18n("Feature Not Yet Available")); m_base->systemRole->setCurrentItem(previousRole); } else { if (bonded) { KMessageBox::error(0, i18n("You are already bonded to a realm!

Please unbond from all realms before selecting a Realm Controller role"), i18n("Common Sense Failure")); m_base->systemRole->setCurrentItem(previousRole); } else { m_roleFullyConfigured = false; // Something will probably change save(); PrimaryRealmWizard realmwizard(this, m_fqdn, m_certconfig, this); if (realmwizard.exec() < 0) { // Wizard was cancelled // Back out all changes! m_base->systemRole->setCurrentItem(previousRole); save(); } else { // Wizard completed; commit changes save(); } m_roleFullyConfigured = true; // Something probably changed load(); } } } else if (m_base->systemRole->currentItem() == ROLE_SECONDARY_REALM_CONTROLLER) { #if 1 // TODO FIXME KMessageBox::error(0, i18n("Secondary realm controller support is not yet available

If you want to see it implemented, contact the Trinity Desktop developers"), i18n("Feature Not Yet Available")); m_base->systemRole->setCurrentItem(previousRole); #else if (previousRole == ROLE_PRIMARY_REALM_CONTROLLER) { // TODO FIXME KMessageBox::error(0, i18n("Primary realm controller demotion is not yet available

If you want to see it implemented, contact the Trinity Desktop developers"), i18n("Feature Not Yet Available")); m_base->systemRole->setCurrentItem(previousRole); } else { if (bonded) { KMessageBox::error(0, i18n("You are already bonded to a realm!

Please unbond from all realms before selecting a Realm Controller role"), i18n("Common Sense Failure")); m_base->systemRole->setCurrentItem(previousRole); } else { m_roleFullyConfigured = false; // Something will probably change save(); SecondaryRealmWizard realmwizard(this, m_fqdn, m_certconfig, this); if (realmwizard.exec() < 0) { // Wizard was cancelled // Back out all changes! m_base->systemRole->setCurrentItem(previousRole); save(); } else { // Wizard completed; commit changes save(); } m_roleFullyConfigured = true; // Something probably changed load(); } } #endif } else if (m_base->systemRole->currentItem() == ROLE_WORKSTATION) { if (KMessageBox::warningYesNo(this, i18n("WARNING
You are attempting to demote a realm controller

This action will PERMANENTLY DESTROY the realm directory stored on this machine

If you do not want to do this, select Cancel below"), i18n("Are you absolutely sure?"), TQString("Continue"), TQString("Cancel")) == KMessageBox::Yes) { ProcessingDialog pdialog(this); pdialog.setStatusMessage(i18n("Preparing to demote primary realm controller...")); pdialog.raise(); pdialog.setActiveWindow(); tqApp->processEvents(); save(); pdialog.setStatusMessage(i18n("Stopping servers...")); // Stop SASL if (controlSASLServer(SC_STOP) != 0) { // } // Stop Heimdal if (controlHeimdalServer(SC_STOP) != 0) { // } // Stop slapd if (controlLDAPServer(SC_STOP) != 0) { // } pdialog.setStatusMessage(i18n("Purging LDAP database...")); tqApp->processEvents(); controlHeimdalServer(SC_PURGE); controlLDAPServer(SC_PURGE); pdialog.setStatusMessage(i18n("Purging local configuration...")); tqApp->processEvents(); system_safe(TQString("rm -f %1").arg(CRON_UPDATE_PRIMARY_REALM_CERTIFICATES_FILE)); system_safe(TQString("rm -rf %1").arg(TDE_CERTIFICATE_DIR)); // Write the TDE realm configuration file LDAPRealmConfigList realms; LDAPManager::writeTDERealmList(realms, m_systemconfig); m_systemconfig->setGroup(NULL); m_systemconfig->deleteEntry("DefaultRealm"); m_systemconfig->deleteGroup("Replication", true, false); m_systemconfig->sync(); pdialog.closeDialog(); load(); } else { m_base->systemRole->setCurrentItem(previousRole); } } } } void LDAPController::processLockouts() { bool enabled = m_base->systemEnableSupport->isChecked(); bool canChangeLDAPEnabled = true; if (getuid() != 0 || !m_systemconfig->checkConfigFilesWritable( true )) { canChangeLDAPEnabled = false; enabled = false; } if (m_base->systemRole->currentItem() != ROLE_WORKSTATION) { canChangeLDAPEnabled = false; } if (m_base->systemRole->currentItem() == ROLE_PRIMARY_REALM_CONTROLLER) { TQListViewItem* lvi = m_base->multiMasterReplicationMappings->selectedItem(); if (lvi) { m_base->btnEditMultiMasterReplicationMapping->setEnabled(true); m_base->btnRemoveMultiMasterReplicationMapping->setEnabled(true); } else { m_base->btnEditMultiMasterReplicationMapping->setEnabled(false); m_base->btnRemoveMultiMasterReplicationMapping->setEnabled(false); } } m_base->systemEnableSupport->setEnabled(canChangeLDAPEnabled); m_base->systemRole->setEnabled(enabled); } void LDAPController::load() { bool thisIsMyMachine; m_systemconfig->setGroup(NULL); m_base->systemEnableSupport->setChecked(m_systemconfig->readBoolEntry("EnableLDAP", false)); if (m_fqdn == m_systemconfig->readEntry("HostFQDN", "")) { thisIsMyMachine = true; } else { thisIsMyMachine = false; } TQString ldapRole = m_systemconfig->readEntry("LDAPRole", "Workstation"); if (!thisIsMyMachine) { ldapRole = "Workstation"; } if (ldapRole == "Primary Realm Controller") { m_base->systemRole->setCurrentItem(ROLE_PRIMARY_REALM_CONTROLLER); } else { m_base->systemRole->setCurrentItem(ROLE_WORKSTATION); } m_prevRole = m_base->systemRole->currentItem(); // Load server-specific replication settings m_systemconfig->setGroup("Replication"); m_base->ignoreReplicationSSLFailures->setChecked(m_systemconfig->readBoolEntry("IgnoreSSLFailures", false)); // Load cert config m_systemconfig->setGroup("Certificates"); m_certconfig.countryName = m_systemconfig->readEntry("countryName"); m_certconfig.stateOrProvinceName = m_systemconfig->readEntry("stateOrProvinceName"); m_certconfig.localityName = m_systemconfig->readEntry("localityName"); m_certconfig.organizationName = m_systemconfig->readEntry("organizationName"); m_certconfig.orgUnitName = m_systemconfig->readEntry("orgUnitName"); m_certconfig.commonName = m_systemconfig->readEntry("commonName"); m_certconfig.emailAddress = m_systemconfig->readEntry("emailAddress"); m_realmconfig = LDAPManager::readTDERealmList(m_systemconfig, !thisIsMyMachine); if (!thisIsMyMachine) { LDAPManager::writeTDERealmList(m_realmconfig, m_systemconfig); } m_systemconfig->setGroup(NULL); m_defaultRealm = m_systemconfig->readEntry("DefaultRealm"); if (m_base->systemRole->currentItem() == ROLE_PRIMARY_REALM_CONTROLLER) { if (m_base->TabWidget2->indexOf(m_base->advancedPrimaryControllerTab) < 0) { m_base->TabWidget2->insertTab(m_base->advancedPrimaryControllerTab, i18n("Advanced Configuration")); } m_base->groupRealmController->show(); m_base->groupRealmCertificates->show(); m_base->realmName->setText(m_defaultRealm); // Display builtin account and group names, and provide a password reset button for each builtin user (yes, this includes the LDAP admin account!) // FIXME // root account should not be locked to "admin"! // when fixing, please fix the two instances of locked "admin": // 1.) in realmwizard.cpp ::accept() // 2.) in LDAPManager::setLDAPMasterReplicationSettings() m_base->ldapRootUser->setText(TQString("cn=%1,").arg("admin") + LDAPManager::ldapdnForRealm(m_defaultRealm)); // Connect to LDAP TQString realmname = m_defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials); TQString errorstring; // Get builtin TDE account mappings from LDAP LDAPTDEBuiltinsInfo builtins = ldap_mgr->getTDEBuiltinMappings(&errorstring); if (m_roleFullyConfigured && errorstring != "") { KMessageBox::error(0, errorstring); } // Get replication mappings from LDAP LDAPMasterReplicationInfo replicationsettings = ldap_mgr->getLDAPMasterReplicationSettings(&errorstring); if (m_roleFullyConfigured && errorstring != "") { KMessageBox::error(0, errorstring); } m_base->advancedEnableMultiMasterReplication->setChecked(replicationsettings.enabled); m_base->multiMasterReplicationMappings->clear(); LDAPMasterReplicationMap::iterator it; for (it = replicationsettings.serverIDs.begin(); it != replicationsettings.serverIDs.end(); ++it) { new TQListViewItem(m_base->multiMasterReplicationMappings, TQString("%1").arg((*it).id), (*it).fqdn); } // Get certificate settings from LDAP TQString realmCAMaster = ldap_mgr->getRealmCAMaster(&errorstring); if (m_roleFullyConfigured && errorstring != "") { KMessageBox::error(0, errorstring); } delete ldap_mgr; delete credentials; m_base->realmAdminUser->setText(LDAPManager::cnFromDn(builtins.builtinRealmAdminAccount)); m_base->realmAdminGroup->setText(LDAPManager::cnFromDn(builtins.builtinRealmAdminGroup)); m_base->realmMachineAdminGroup->setText(LDAPManager::cnFromDn(builtins.builtinMachineAdminGroup)); m_base->realmStandardUserGroup->setText(LDAPManager::cnFromDn(builtins.builtinStandardUserGroup)); m_base->caCurrentMaster->setText(realmCAMaster); if (m_fqdn == realmCAMaster) { m_base->caSetMaster->setEnabled(false); } else { m_base->caSetMaster->setEnabled(true); } updateCertDisplay(); m_certRefreshTimer.start(60*1000); } else { if (m_base->TabWidget2->indexOf(m_base->advancedPrimaryControllerTab) >= 0) { m_base->TabWidget2->removePage(m_base->advancedPrimaryControllerTab); } m_base->groupRealmController->hide(); m_base->groupRealmCertificates->hide(); m_certRefreshTimer.stop(); } processLockouts(); } #define CERT_STATUS_COLOR_ACTIVE TQColor(0, 128, 0) #define CERT_STATUS_COLOR_STALE TQColor(128, 64, 0) #define CERT_STATUS_COLOR_EXPIRED TQColor(128, 0, 0) #define CERT_STATUS_COLOR_NOTFOUND CERT_STATUS_COLOR_EXPIRED void LDAPController::updateCertDisplay() { TQDateTime certExpiry; TQDateTime now = TQDateTime::currentDateTime(); TQDateTime soon = now.addDays(7); // Keep in sync with cert-updater/main.cpp TQString kdc_certfile = KERBEROS_PKI_KDC_FILE; kdc_certfile.replace("@@@KDCSERVER@@@", m_realmconfig[m_defaultRealm].kdc); TQString ldap_certfile = LDAP_CERT_FILE; ldap_certfile.replace("@@@ADMINSERVER@@@", m_realmconfig[m_defaultRealm].admin_server); // Certificate Authority if (TQFile::exists(KERBEROS_PKI_PEM_FILE)) { certExpiry = LDAPManager::getCertificateExpiration(KERBEROS_PKI_PEM_FILE); if (certExpiry >= now) { m_base->caExpiryString->setText("Expires " + certExpiry.toString()); if (certExpiry >= soon) { m_base->caExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_ACTIVE); } else { m_base->caExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_STALE); } } else { m_base->caExpiryString->setText("Expired " + certExpiry.toString()); m_base->caExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_EXPIRED); } } else { m_base->caExpiryString->setText("File not found"); m_base->caExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_NOTFOUND); } // Kerberos if (TQFile::exists(kdc_certfile)) { certExpiry = LDAPManager::getCertificateExpiration(kdc_certfile); if (certExpiry >= now) { m_base->krbExpiryString->setText("Expires " + certExpiry.toString()); if (certExpiry >= soon) { m_base->krbExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_ACTIVE); } else { m_base->krbExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_STALE); } } else { m_base->krbExpiryString->setText("Expired " + certExpiry.toString()); m_base->krbExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_EXPIRED); } } else { m_base->krbExpiryString->setText("File not found"); m_base->krbExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_NOTFOUND); } // LDAP if (TQFile::exists(ldap_certfile)) { certExpiry = LDAPManager::getCertificateExpiration(ldap_certfile); if (certExpiry >= now) { m_base->ldapExpiryString->setText("Expires " + certExpiry.toString()); if (certExpiry >= soon) { m_base->ldapExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_ACTIVE); } else { m_base->ldapExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_STALE); } } else { m_base->ldapExpiryString->setText("Expired " + certExpiry.toString()); m_base->ldapExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_EXPIRED); } } else { m_base->ldapExpiryString->setText("File not found"); m_base->ldapExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_NOTFOUND); } } void LDAPController::btncaSetMaster() { if (KMessageBox::warningYesNo(this, i18n("You are about to promote the server '%1' to the role of Certificate Authority Master

Are you sure you want to proceed?").arg(m_fqdn), i18n("Confirmation Required")) == KMessageBox::Yes) { TQString errorstring; TQString realmname = m_defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials); if (ldap_mgr->setRealmCAMaster(m_fqdn, &errorstring) != 0) { KMessageBox::error(0, i18n("Unable to change certificate authority master server!

%1").arg(errorstring), i18n("Internal Failure")); delete ldap_mgr; load(); return; } LDAPManager::generatePublicKerberosCACertificate(m_certconfig); // Upload the contents of KERBEROS_PKI_PEM_FILE to the LDAP server if (uploadKerberosCAFileToLDAP(ldap_mgr, &errorstring) != 0) { KMessageBox::error(0, i18n("Unable to upload new certificate to LDAP server!

%1").arg(errorstring), i18n("Internal Failure")); } delete ldap_mgr; load(); } } void LDAPController::btncaRegenerate() { LDAPManager::generatePublicKerberosCACertificate(m_certconfig); TQString realmname = m_defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials); // Upload the contents of KERBEROS_PKI_PEM_FILE to the LDAP server TQString errorstring; if (uploadKerberosCAFileToLDAP(ldap_mgr, &errorstring) != 0) { KMessageBox::error(0, i18n("Unable to upload new certificate to LDAP server!

%1").arg(errorstring), i18n("Internal Failure")); } delete ldap_mgr; load(); } void LDAPController::btncaExportKey() { KURL src = KERBEROS_PKI_PEMKEY_FILE; KURL dest = KFileDialog::getSaveURL(TQString::null, "*.key|Private Key (*.key)", this, i18n("Select a location to save a copy of the private key...")); if (!dest.isEmpty()) { TDEIO::CopyJob* job = TDEIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(slotCertCopyResult(TDEIO::Job*))); } } void LDAPController::btncaExportCert() { KURL src = KERBEROS_PKI_PEM_FILE; KURL dest = KFileDialog::getSaveURL(TQString::null, "*.pem|PKI Certificate Files (*.pem)", this, i18n("Select a location to save a copy of the certificate...")); if (!dest.isEmpty()) { TDEIO::CopyJob* job = TDEIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(slotCertCopyResult(TDEIO::Job*))); } } void LDAPController::btnkrbRegenerate() { LDAPManager::generatePublicKerberosCertificate(m_certconfig, m_realmconfig[m_defaultRealm]); load(); } void LDAPController::btnkrbExportKey() { TQString kdc_keyfile = KERBEROS_PKI_KDCKEY_FILE; kdc_keyfile.replace("@@@KDCSERVER@@@", m_realmconfig[m_defaultRealm].kdc); KURL src = kdc_keyfile; KURL dest = KFileDialog::getSaveURL(TQString::null, "*.key|Private Key (*.key)", this, i18n("Select a location to save a copy of the private key...")); if (!dest.isEmpty()) { TDEIO::CopyJob* job = TDEIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(slotCertCopyResult(TDEIO::Job*))); } } void LDAPController::btnkrbExportCert() { TQString kdc_certfile = KERBEROS_PKI_KDC_FILE; kdc_certfile.replace("@@@KDCSERVER@@@", m_realmconfig[m_defaultRealm].kdc); KURL src = kdc_certfile; KURL dest = KFileDialog::getSaveURL(TQString::null, "*.pem|PKI Certificate Files (*.pem)", this, i18n("Select a location to save a copy of the certificate...")); if (!dest.isEmpty()) { TDEIO::CopyJob* job = TDEIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(slotCertCopyResult(TDEIO::Job*))); } } void LDAPController::btnldapRegenerate() { uid_t slapd_uid = 0; gid_t slapd_gid = 0; // Get LDAP user uid/gid struct passwd *pwd; pwd = getpwnam(m_ldapUserName); slapd_uid = pwd->pw_uid; slapd_gid = pwd->pw_gid; LDAPManager::generatePublicLDAPCertificate(m_certconfig, m_realmconfig[m_defaultRealm], slapd_uid, slapd_gid); load(); } void LDAPController::btnldapExportKey() { TQString ldap_keyfile = LDAP_CERTKEY_FILE; ldap_keyfile.replace("@@@ADMINSERVER@@@", m_realmconfig[m_defaultRealm].admin_server); KURL src = ldap_keyfile; KURL dest = KFileDialog::getSaveURL(TQString::null, "*.key|Private Key (*.key)", this, i18n("Select a location to save a copy of the private key...")); if (!dest.isEmpty()) { TDEIO::CopyJob* job = TDEIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(slotCertCopyResult(TDEIO::Job*))); } } void LDAPController::btnldapExportCert() { TQString ldap_certfile = LDAP_CERT_FILE; ldap_certfile.replace("@@@ADMINSERVER@@@", m_realmconfig[m_defaultRealm].admin_server); KURL src = ldap_certfile; KURL dest = KFileDialog::getSaveURL(TQString::null, "*.pem|PKI Certificate Files (*.pem)", this, i18n("Select a location to save a copy of the certificate...")); if (!dest.isEmpty()) { TDEIO::CopyJob* job = TDEIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(slotCertCopyResult(TDEIO::Job*))); } } void LDAPController::slotCertCopyResult(TDEIO::Job* job) { if (job->error()) { job->showErrorDialog(this); } } void LDAPController::btnChangeLDAPRootPassword() { // NOTE // There is (currently) no good way to replace the root password // This convoluted procedure is (currently) the best I can do... bool ret = false; TQCString rootPassword; int result = KPasswordDialog::getNewPassword(rootPassword, i18n("Please enter the new LDAP root password:")); if (result == KPasswordDialog::Accepted) { SHA1 sha; sha.process(rootPassword, strlen(rootPassword)); TQString rootpw_hash = sha.base64Hash(); TQString oldconfigfilename = "/etc/ldap/slapd.d/cn=config/" + TQString("olcDatabase={%1}hdb.ldif.bkp").arg(1); TQString newconfigfilename = "/etc/ldap/slapd.d/cn=config/" + TQString("olcDatabase={%1}hdb.ldif").arg(1); if (controlLDAPServer(SC_STOP) == 0) { rename(newconfigfilename.ascii(), oldconfigfilename.ascii()); TQFile ifile(oldconfigfilename); TQFile ofile(newconfigfilename); if (ifile.open(IO_ReadOnly)) { if (ofile.open(IO_WriteOnly)) { TQString line; TQTextStream istream(&ifile); TQTextStream ostream(&ofile); while (!istream.atEnd()) { line = istream.readLine(); if (line.startsWith("olcRootPW:")) { ostream << "olcRootPW: {SHA}" << rootpw_hash << "\n"; } else { ostream << line << "\n"; } } ifile.close(); unlink(oldconfigfilename); ofile.close(); if (controlLDAPServer(SC_START) == 0) { ret = true; } } else { ifile.close(); rename(oldconfigfilename.ascii(), newconfigfilename.ascii()); } } else { rename(oldconfigfilename.ascii(), newconfigfilename.ascii()); } } if (!ret) { KMessageBox::error(0, i18n("Unable to modify LDAP root password

Your LDAP server may now be in an inconsistent or disabled state"), i18n("Internal Failure")); } } } void LDAPController::btnChangeRealmAdminPassword() { TQCString adminPassword; int result = KPasswordDialog::getNewPassword(adminPassword, i18n("Please enter the new realm administrator password:")); if (result == KPasswordDialog::Accepted) { TQString realmname = m_defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials); TQString errorstring; LDAPTDEBuiltinsInfo builtins = ldap_mgr->getTDEBuiltinMappings(&errorstring); LDAPUserInfo adminuserinfo = ldap_mgr->getUserByDistinguishedName(builtins.builtinRealmAdminAccount); if (adminuserinfo.informationValid) { adminuserinfo.new_password = adminPassword; ldap_mgr->setPasswordForUser(adminuserinfo, &errorstring); m_systemconfig->setGroup("Replication"); m_systemconfig->writeEntry("Password", adminPassword.data()); m_systemconfig->setGroup(NULL); m_systemconfig->sync(); } delete ldap_mgr; delete credentials; } } void LDAPController::btnAddMultiMasterReplicationMapping() { // Launch a dialog to add the mapping LDAPMasterReplicationMapping mapping; bool run = true; MultiMasterReplicationConfigDialog mappingconfigdlg(mapping, m_defaultRealm, this); while (run && (mappingconfigdlg.exec() == TQDialog::Accepted)) { mapping = mappingconfigdlg.m_replicationProperties; // Make sure the provided FQDN and/or UID do not already exist bool conflict = false; TQPtrList lst; TQListViewItemIterator it(m_base->multiMasterReplicationMappings); while (it.current()) { if (it.current()->text(0).toInt() == mapping.id) { conflict = true; KMessageBox::error(0, i18n("Unable to add new multi-master replication!

The provided ID '%1' conflicts with an existing replication mapping.").arg(mapping.id), i18n("Invalid Configuration")); break; } if (it.current()->text(1) == mapping.fqdn) { conflict = true; KMessageBox::error(0, i18n("Unable to add new multi-master replication!

The provided FQDN '%1' conflicts with an existing replication mapping.").arg(mapping.fqdn), i18n("Invalid Configuration")); break; } ++it; } if (conflict) { run = true; } else { run = false; new TQListViewItem(m_base->multiMasterReplicationMappings, TQString("%1").arg(mapping.id), mapping.fqdn); changed(); } } } void LDAPController::btnEditMultiMasterReplicationMapping() { // Launch a dialog to edit the mapping LDAPMasterReplicationMapping mapping; TQListViewItem* lvi = m_base->multiMasterReplicationMappings->selectedItem(); if (!lvi) { return; } mapping.id = lvi->text(0).toInt(); mapping.fqdn = lvi->text(1); bool run = true; MultiMasterReplicationConfigDialog mappingconfigdlg(mapping, m_defaultRealm, this); while (run && (mappingconfigdlg.exec() == TQDialog::Accepted)) { mapping = mappingconfigdlg.m_replicationProperties; // Make sure the provided FQDN and/or UID do not already exist bool conflict = false; TQPtrList lst; TQListViewItemIterator it(m_base->multiMasterReplicationMappings); while (it.current()) { if (it.current() == lvi) { // The selected item will be removed on update, so ignore any conflicts with it... ++it; continue; } if (it.current()->text(0).toInt() == mapping.id) { conflict = true; KMessageBox::error(0, i18n("Unable to add new multi-master replication!

The provided ID '%1' conflicts with an existing replication mapping.").arg(mapping.id), i18n("Invalid Configuration")); break; } if (it.current()->text(1) == mapping.fqdn) { conflict = true; KMessageBox::error(0, i18n("Unable to add new multi-master replication!

The provided FQDN '%1' conflicts with an existing replication mapping.").arg(mapping.fqdn), i18n("Invalid Configuration")); break; } ++it; } if (conflict) { run = true; } else { run = false; if (lvi) { delete lvi; } new TQListViewItem(m_base->multiMasterReplicationMappings, TQString("%1").arg(mapping.id), mapping.fqdn); changed(); } } } void LDAPController::btnRemoveMultiMasterReplicationMapping() { LDAPMasterReplicationMapping mapping; TQListViewItem* lvi = m_base->multiMasterReplicationMappings->selectedItem(); if (!lvi) { return; } mapping.id = lvi->text(0).toInt(); mapping.fqdn = lvi->text(1); if (KMessageBox::warningYesNo(this, i18n("You are about to remove the muli-master replication mapping for '%1'
This action cannot be undone once committed

Are you sure you want to proceed?").arg(mapping.fqdn), i18n("Confirmation Required")) == KMessageBox::Yes) { delete lvi; changed(); } } void LDAPController::multiMasterReplicationHighlighted() { processLockouts(); } void LDAPController::modifySelectedMultiMasterReplication() { btnEditMultiMasterReplicationMapping(); } void LDAPController::defaults() { // } void LDAPController::save() { TQString prevRole = m_systemconfig->readEntry("LDAPRole", "Workstation"); m_systemconfig->setGroup(NULL); m_systemconfig->writeEntry("EnableLDAP", m_base->systemEnableSupport->isChecked()); m_systemconfig->writeEntry("HostFQDN", m_fqdn); m_systemconfig->writeEntry("LDAPRole", m_base->systemRole->currentText()); // Write server-specific replication settings m_systemconfig->setGroup("Replication"); m_systemconfig->writeEntry("IgnoreSSLFailures", m_base->ignoreReplicationSSLFailures->isChecked()); // Write cert config m_systemconfig->setGroup("Certificates"); m_systemconfig->writeEntry("countryName", m_certconfig.countryName); m_systemconfig->writeEntry("stateOrProvinceName", m_certconfig.stateOrProvinceName); m_systemconfig->writeEntry("localityName", m_certconfig.localityName); m_systemconfig->writeEntry("organizationName", m_certconfig.organizationName); m_systemconfig->writeEntry("orgUnitName", m_certconfig.orgUnitName); m_systemconfig->writeEntry("commonName", m_certconfig.commonName); m_systemconfig->writeEntry("emailAddress", m_certconfig.emailAddress); m_systemconfig->setGroup(NULL); m_systemconfig->sync(); // If role was not changed, update any role-specific advanced settings if (prevRole == m_systemconfig->readEntry("LDAPRole", "Workstation")) { if (m_base->systemRole->currentItem() == ROLE_PRIMARY_REALM_CONTROLLER) { TQString realmname = m_defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials); TQString errorstring; // Write multi-master replication settings LDAPMasterReplicationInfo replicationSettings; replicationSettings.enabled = m_base->advancedEnableMultiMasterReplication->isChecked(); replicationSettings.serverIDs.clear(); TQPtrList lst; TQListViewItemIterator it(m_base->multiMasterReplicationMappings); while (it.current()) { LDAPMasterReplicationMapping mapping; mapping.id = it.current()->text(0).toInt(); mapping.fqdn = it.current()->text(1); replicationSettings.serverIDs.append(mapping); ++it; } // Use the local password for inter-master authentication // All realm controllers in a realm must (obviously) use the same admin/config password! m_systemconfig->setGroup("Replication"); replicationSettings.syncPassword = m_systemconfig->readEntry("Password"); m_systemconfig->setGroup(NULL); // Use the TDE LDAP CA for replication TLS replicationSettings.caCertificateFile = KERBEROS_PKI_PEM_FILE; replicationSettings.ignore_ssl_failure = m_base->ignoreReplicationSSLFailures->isChecked(); if (ldap_mgr->setLDAPMasterReplicationSettings(replicationSettings, NULL) != 0) { // ERROR } } } load(); } void replacePlaceholdersInFile(TQString infile, TQString outfile, LDAPRealmConfig realmconfig, TQString adminUserName, TQString adminGroupName, TQString machineAdminGroupName, TQString standardUserGroupName, const char * adminPassword, TQString rootUserName, const char * rootPassword, int ldifSchemaNumber=-1, uid_t userid=-1, gid_t groupid=-1, TQString ldapusername=TQString::null, TQString ldapgroupname=TQString::null) { SHA1 sha; sha.process(rootPassword, strlen(rootPassword)); TQString rootpw_hash = sha.base64Hash(); sha.reset(); sha.process(adminPassword, strlen(rootPassword)); TQString adminpw_hash = sha.base64Hash(); // Created needed strings TQStringList domainChunks = TQStringList::split(".", realmconfig.name.lower()); TQString basedcname = "dc=" + domainChunks.join(",dc="); TQString simpledcname = domainChunks[0]; TQString simpledcnamecap = simpledcname.lower(); simpledcnamecap[0] = simpledcnamecap[0].upper(); TQString timestamp = TQDateTime::currentDateTime().toString(TQt::ISODate); timestamp.replace("-", ""); timestamp.replace(":", ""); timestamp.replace("T", ""); TQString uuid; TQUuid randomUUID = TQUuid::createUuid(); uuid = randomUUID.toString(); uuid.replace("{", ""); uuid.replace("}", ""); TQString kdc_certfile = KERBEROS_PKI_KDC_FILE; TQString kdc_keyfile = KERBEROS_PKI_KDCKEY_FILE; TQString ldap_certfile = LDAP_CERT_FILE; TQString ldap_keyfile = LDAP_CERTKEY_FILE; kdc_certfile.replace("@@@KDCSERVER@@@", realmconfig.kdc); kdc_keyfile.replace("@@@KDCSERVER@@@", realmconfig.kdc); ldap_certfile.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); ldap_keyfile.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); TQFile ifile(infile); TQFile ofile(outfile); if (ifile.open(IO_ReadOnly)) { if (ofile.open(IO_WriteOnly)) { TQString line; TQTextStream istream(&ifile); TQTextStream ostream(&ofile); while (!istream.atEnd()) { line = istream.readLine(); line.replace("@@@REALM_DCNAME@@@", basedcname); line.replace("@@@REALM_UCNAME@@@", realmconfig.name.upper()); line.replace("@@@REALM_LCNAME@@@", realmconfig.name.lower()); line.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); line.replace("@@@ADMINPORT@@@", TQString("%1").arg(realmconfig.admin_server_port)); line.replace("@@@KDCSERVER@@@", realmconfig.kdc); line.replace("@@@KDCPORT@@@", TQString("%1").arg(realmconfig.kdc_port)); line.replace("@@@ROOTUSER@@@", rootUserName); line.replace("@@@ROOTPW_SHA@@@", rootpw_hash); line.replace("@@@ADMINUSER@@@", adminUserName); line.replace("@@@ADMINGROUP@@@", adminGroupName); line.replace("@@@LOCALADMINGROUP@@@", machineAdminGroupName); line.replace("@@@STANDARDUSERGROUP@@@", standardUserGroupName); line.replace("@@@ADMINPW_SHA@@@", adminpw_hash); line.replace("@@@PKINIT_REQUIRE_EKU@@@", (realmconfig.pkinit_require_eku)?"yes":"no"); line.replace("@@@PKINIT_REQUIRE_KRBTGT_OTHERNAME@@@", (realmconfig.pkinit_require_krbtgt_otherName)?"yes":"no"); line.replace("@@@WIN2K_PKINIT@@@", (realmconfig.win2k_pkinit)?"yes":"no"); line.replace("@@@WIN2K_PKINIT_REQUIRE_BINDING@@@", (realmconfig.win2k_pkinit_require_binding)?"yes":"no"); line.replace("@@@REALM_SIMPLE_CP_NAME@@@", simpledcnamecap); line.replace("@@@REALM_SIMPLE_LC_NAME@@@", simpledcname.lower()); line.replace("@@@TIMESTAMP@@@", timestamp); line.replace("@@@ENTRYUUID@@@", uuid); line.replace("@@@LDAP_KEYTAB_FILE@@@", LDAP_KEYTAB_FILE); line.replace("@@@LDAP_USER_NAME@@@", ldapusername); line.replace("@@@LDAP_GROUP_NAME@@@", ldapgroupname); line.replace("@@@TDELIBDIR@@@", TDE_LIBDIR); line.replace("@@@HEIMDALACLFILE@@@", HEIMDAL_ACL_FILE); line.replace("@@@KRBPKIPEMFILE@@@", KERBEROS_PKI_PEM_FILE); line.replace("@@@KRBPKIPEMKEYFILE@@@", KERBEROS_PKI_PEMKEY_FILE); line.replace("@@@KRBKDCPEMFILE@@@", kdc_certfile); line.replace("@@@KRBKDCPEMKEYFILE@@@", kdc_keyfile); line.replace("@@@LDAPPEMFILE@@@", ldap_certfile); line.replace("@@@LDAPPEMKEYFILE@@@", ldap_keyfile); if (ldifSchemaNumber >= 0) { line.replace("@@@LDIFSCHEMANUMBER@@@", TQString("%1").arg(ldifSchemaNumber)); } ostream << line << "\n"; } ofile.close(); // Set permissions if ((userid > 0) && (groupid > 0)) { chown_safe(outfile.ascii(), userid, groupid); } } else { //KMessageBox::error(0, i18n("Unable to open output schema file %1 for writing").arg(outfile), i18n("Internal Failure")); printf("[INTERNAL FAILURE] Unable to open output schema file %s for writing\n\r", outfile.ascii()); fflush(stdout); } ifile.close(); } else { //KMessageBox::error(0, i18n("Unable to open template schema file %1").arg(infile), i18n("Internal Failure")); printf("[INTERNAL FAILURE] Unable to open template schema file %s\n\r", infile.ascii()); fflush(stdout); } // Keep UI responsive tqApp->processEvents(); } int LDAPController::controlKAdminDaemon(sc_command command) { if (command == SC_RESTART) { // FIXME // This assumes Debian! return system("/etc/init.d/openbsd-inetd restart"); } return -2; } int LDAPController::controlSASLServer(sc_command command) { if (command == SC_START) { // FIXME // This assumes Debian! return system("/etc/init.d/saslauthd start"); } if (command == SC_STOP) { // FIXME // This assumes Debian! return system("/etc/init.d/saslauthd stop"); } if (command == SC_RESTART) { // FIXME // This assumes Debian! return system("/etc/init.d/saslauthd restart"); } return -2; } int LDAPController::controlHeimdalServer(sc_command command, uid_t userid, gid_t groupid) { if (command == SC_START) { // FIXME // This assumes Debian! return system("/etc/init.d/heimdal-kdc start"); } if (command == SC_STOP) { // FIXME // This assumes Debian! return system("/etc/init.d/heimdal-kdc stop"); } if (command == SC_RESTART) { // FIXME // This assumes Debian! return system("/etc/init.d/heimdal-kdc restart"); } if (command == SC_PURGE) { controlHeimdalServer(SC_STOP); system_safe("rm -f " + TQString(LDAP_KEYTAB_FILE)); // FIXME // This assumes Debian system_safe("rm -f /etc/krb5.keytab"); system_safe("rm -rf /var/lib/heimdal-kdc/*"); } if (command == SC_SETDBPERMS) { if ((userid > 0) && (groupid > 0)) { TQString command; command = TQString("chgrp %1 " + TQString(LDAP_KEYTAB_FILE)).arg(groupid); system_safe(command.ascii()); chmod(LDAP_KEYTAB_FILE, S_IRUSR|S_IWUSR|S_IRGRP); } } return -2; } int LDAPController::controlLDAPServer(sc_command command, uid_t userid, gid_t groupid) { if (command == SC_START) { // FIXME // This assumes Debian! return system("/etc/init.d/slapd start"); } if (command == SC_STOP) { // FIXME // This assumes Debian! return system("/etc/init.d/slapd stop"); } if (command == SC_RESTART) { // FIXME // This assumes Debian! return system("/etc/init.d/slapd restart"); } if (command == SC_PURGE) { controlLDAPServer(SC_STOP); // FIXME // This assumes Debian! system_safe("rm -rf /var/lib/ldap/*"); system_safe("rm -rf /etc/ldap/slapd.d/*"); } if (command == SC_SETDBPERMS) { if ((userid > 0) && (groupid > 0)) { // FIXME // This assumes Debian! TQString command; command = TQString("chown -R %1 /var/lib/ldap/*").arg(userid); system_safe(command.ascii()); command = TQString("chgrp -R %1 /var/lib/ldap/*").arg(groupid); system_safe(command.ascii()); command = TQString("chown -R %1 /etc/ldap/slapd.d/*").arg(userid); system_safe(command.ascii()); command = TQString("chgrp -R %1 /etc/ldap/slapd.d/*").arg(groupid); system_safe(command.ascii()); } } return -2; } int LDAPController::initializeNewKerberosRealm(TQString realmName, TQString *errstr) { TQCString command = "kadmin"; QCStringList args; args << TQCString("-l"); TQString prompt; PtyProcess kadminProc; kadminProc.enableLocalEcho(false); kadminProc.exec(command, args); prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { command = TQCString("init "+realmName); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } else if (prompt.startsWith("Realm max")) { command = "unlimited"; kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); if (prompt.startsWith("Realm max")) { command = "unlimited"; kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); } if (prompt != "kadmin>") { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } if (errstr) *errstr = "Internal error. Verify that kadmin exists and can be executed."; return 1; // Failure } int LDAPController::addHostEntryToKerberosRealm(TQString kerberosHost, TQString *errstr) { TQCString command = "kadmin"; QCStringList args; args << TQCString("-l"); TQString hoststring = "host/"+kerberosHost; TQString prompt; PtyProcess kadminProc; kadminProc.exec(command, args); prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { command = TQCString("ext "+hoststring); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } else if (prompt.endsWith("Principal does not exist")) { prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt != "kadmin>") { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } command = TQCString("ank --random-key "+hoststring); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); // Use all defaults while (prompt != "kadmin>") { if (prompt.contains("authentication failed")) { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } else { // Extract whatever default is in the [brackets] and feed it back to kadmin TQString defaultParam; int leftbracket = prompt.find("["); int rightbracket = prompt.find("]"); if ((leftbracket >= 0) && (rightbracket >= 0)) { leftbracket++; defaultParam = prompt.mid(leftbracket, rightbracket-leftbracket); } command = TQCString(defaultParam); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); } } command = TQCString("ext "+hoststring); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); if (prompt != "kadmin>") { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } else if (prompt == "kadmin>") { // Success! kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } if (errstr) *errstr = "Internal error. Verify that kadmin exists and can be executed."; return 1; // Failure } int LDAPController::addLDAPEntryToKerberosRealm(TQString ldapProcessOwnerName, TQString ldapHost, TQString *errstr) { TQCString command = "kadmin"; QCStringList args; args << TQCString("-l"); TQString hoststring = ldapProcessOwnerName+"/"+ldapHost; TQString prompt; PtyProcess kadminProc; kadminProc.exec(command, args); prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { command = TQCString("ext --keytab="+TQString(LDAP_KEYTAB_FILE)+" "+hoststring); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt.startsWith("ext --keytab=")); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } else if (prompt.endsWith("Principal does not exist")) { prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt != "kadmin>") { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } command = TQCString("ank --random-key "+hoststring); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); // Use all defaults while (prompt != "kadmin>") { if (prompt.contains("authentication failed")) { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } else { // Extract whatever default is in the [brackets] and feed it back to kadmin TQString defaultParam; int leftbracket = prompt.find("["); int rightbracket = prompt.find("]"); if ((leftbracket >= 0) && (rightbracket >= 0)) { leftbracket++; defaultParam = prompt.mid(leftbracket, rightbracket-leftbracket); } command = TQCString(defaultParam); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); } } command = TQCString("ext --keytab="+TQString(LDAP_KEYTAB_FILE)+" "+hoststring); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt.startsWith("ext --keytab=")); prompt = prompt.stripWhiteSpace(); if (prompt != "kadmin>") { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } else if (prompt == "kadmin>") { // Success! kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } if (errstr) *errstr = "Internal error. Verify that kadmin exists and can be executed."; return 1; // Failure } int LDAPController::setKerberosPasswordForUser(LDAPCredentials user, TQString *errstr) { if (user.password == "") { return 0; } TQCString command = "kadmin"; QCStringList args; args << TQCString("-l") << TQCString("-r") << TQCString(user.realm.upper()); TQString prompt; PtyProcess kadminProc; kadminProc.exec(command, args); prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { command = TQCString("passwd "+user.username); kadminProc.enableLocalEcho(false); kadminProc.writeLine(command, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == TQString(command)); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } else if ((prompt.endsWith(" Password:")) && (prompt.startsWith(TQString(user.username + "@")))) { kadminProc.enableLocalEcho(false); kadminProc.writeLine(user.password, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == ""); prompt = prompt.stripWhiteSpace(); if ((prompt.endsWith(" Password:")) && (prompt.startsWith("Verify"))) { kadminProc.enableLocalEcho(false); kadminProc.writeLine(user.password, true); do { // Discard our own input prompt = LDAPManager::readFullLineFromPtyProcess(&kadminProc); printf("(kadmin) '%s'\n\r", prompt.ascii()); } while (prompt == ""); prompt = prompt.stripWhiteSpace(); } if (prompt != "kadmin>") { if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } else if (prompt == "kadmin>") { // Success! kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = LDAPManager::detailedKAdminErrorMessage(prompt); kadminProc.enableLocalEcho(false); kadminProc.writeLine("quit", true); return 1; } if (errstr) *errstr = "Internal error. Verify that kadmin exists and can be executed."; return 1; // Failure } int LDAPController::createRealmCertificates(LDAPCertConfig certinfo, LDAPRealmConfig realmconfig, uid_t ldap_uid, gid_t ldap_gid) { // Certificate authority certificate TQString command; command = TQString("openssl genrsa -out %1 %2").arg(KERBEROS_PKI_PEMKEY_FILE).arg(KEY_STRENGTH); system_safe(command); chmod(KERBEROS_PKI_PEMKEY_FILE, S_IRUSR|S_IWUSR); chown_safe(KERBEROS_PKI_PEMKEY_FILE, 0, 0); LDAPManager::generatePublicKerberosCACertificate(certinfo); // KDC certificate TQString kdc_certfile = KERBEROS_PKI_KDC_FILE; TQString kdc_keyfile = KERBEROS_PKI_KDCKEY_FILE; TQString kdc_reqfile = KERBEROS_PKI_KDCREQ_FILE; kdc_certfile.replace("@@@KDCSERVER@@@", realmconfig.kdc); kdc_keyfile.replace("@@@KDCSERVER@@@", realmconfig.kdc); kdc_reqfile.replace("@@@KDCSERVER@@@", realmconfig.kdc); command = TQString("openssl genrsa -out %1 %2").arg(kdc_keyfile).arg(KEY_STRENGTH); system_safe(command); chmod(kdc_keyfile.ascii(), S_IRUSR|S_IWUSR); chown_safe(kdc_keyfile.ascii(), 0, 0); LDAPManager::generatePublicKerberosCertificate(certinfo, realmconfig); // LDAP certificate TQString ldap_certfile = LDAP_CERT_FILE; TQString ldap_keyfile = LDAP_CERTKEY_FILE; TQString ldap_reqfile = LDAP_CERTREQ_FILE; ldap_certfile.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); ldap_keyfile.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); ldap_reqfile.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); command = TQString("openssl genrsa -out %1 %2").arg(ldap_keyfile).arg(KEY_STRENGTH); system_safe(command); chmod(ldap_keyfile.ascii(), S_IRUSR|S_IWUSR); chown_safe(ldap_keyfile.ascii(), ldap_uid, ldap_gid); LDAPManager::generatePublicLDAPCertificate(certinfo, realmconfig, ldap_uid, ldap_gid); return 0; } int LDAPController::uploadKerberosCAFileToLDAP(LDAPManager* ldap_mgr, TQString* errstr) { // Upload the contents of KERBEROS_PKI_PEM_FILE to the LDAP server TQFile cafile(KERBEROS_PKI_PEM_FILE); if (cafile.open(IO_ReadOnly)) { TQByteArray cafiledata = cafile.readAll(); if (ldap_mgr->writeCertificateFileIntoDirectory(cafiledata, "publicRootCertificate", errstr) != 0) { return -1; } return 0; } return -1; } int LDAPController::uploadKerberosCAKeyFileToLDAP(LDAPManager* ldap_mgr, TQString* errstr) { // Upload the contents of KERBEROS_PKI_PEMKEY_FILE to the LDAP server TQFile cafile(KERBEROS_PKI_PEMKEY_FILE); if (cafile.open(IO_ReadOnly)) { TQByteArray cafiledata = cafile.readAll(); if (ldap_mgr->writeCertificateFileIntoDirectory(cafiledata, "privateRootCertificateKey", errstr) != 0) { return -1; } return 0; } return -1; } // #define STRICT_SETUP 1 int LDAPController::createNewSecondaryController(TQWidget* dialogparent, LDAPRealmConfig realmconfig, TQString adminUserName, const char * adminPassword, TQString adminRealm, TQString *errstr) { // Fortunately this is somewhat simpler than createNewLDAPRealm(...)! ProcessingDialog pdialog(dialogparent); pdialog.setStatusMessage(i18n("Loading data for secondary controller...")); pdialog.raise(); pdialog.setActiveWindow(); tqApp->processEvents(); // TODO FIXME // Threading would be a good idea here, to keep the GUI responsive while the backend code works // Reset improperly uninitialized variables realmconfig.bonded = true; // Find the templates TQString templateDir = locate("data", "kcmldapcontroller/skel/heimdal/heimdal.defaults"); templateDir.replace("heimdal/heimdal.defaults", ""); if (templateDir == "") { if (errstr) *errstr = i18n("Unable to locate required template files"); pdialog.closeDialog(); return -1; } KTempDir configTempDir; configTempDir.setAutoDelete(true); TQString destDir = "/etc/"; pdialog.setStatusMessage(i18n("Stopping servers...")); // Stop SASL if (controlSASLServer(SC_STOP) != 0) { #ifdef STRICT_SETUP if (errstr) *errstr = i18n("Unable to stop SASL server"); pdialog.closeDialog(); return -1; #endif // STRICT_SETUP } // Stop Heimdal if (controlHeimdalServer(SC_STOP) != 0) { #ifdef STRICT_SETUP if (errstr) *errstr = i18n("Unable to stop Kerberos server"); pdialog.closeDialog(); return -1; #endif // STRICT_SETUP } // Stop slapd if (controlLDAPServer(SC_STOP) != 0) { #ifdef STRICT_SETUP if (errstr) *errstr = i18n("Unable to stop LDAP server"); pdialog.closeDialog(); return -1; #endif // STRICT_SETUP } // TODO FIXME // 1.) Fetch CA private/public certificates from master LDAP server, save them, and also use the public certificate to fill a certificate information structure // 2.) Bond machine to Kerberos // 3.) Set up LDAP replication // 4.) Point local Kerberos and SASL instances to this LDAP server return -1; } int LDAPController::createNewLDAPRealm(TQWidget* dialogparent, LDAPRealmConfig realmconfig, TQString adminUserName, TQString adminGroupName, TQString machineAdminGroupName, TQString standardUserGroupName, const char * adminPassword, TQString rootUserName, const char * rootPassword, TQString adminRealm, LDAPCertConfig certinfo, TQString *errstr) { Q_UNUSED(adminRealm) int ldifSchemaNumber; ProcessingDialog pdialog(dialogparent); pdialog.setStatusMessage(i18n("Loading data for realm deployment...")); pdialog.raise(); pdialog.setActiveWindow(); tqApp->processEvents(); // TODO FIXME // Threading would be a good idea here, to keep the GUI responsive while the backend code works // Reset improperly uninitialized variables realmconfig.bonded = true; // Find the templates TQString templateDir = locate("data", "kcmldapcontroller/skel/heimdal/heimdal.defaults"); templateDir.replace("heimdal/heimdal.defaults", ""); if (templateDir == "") { if (errstr) *errstr = i18n("Unable to locate required template files"); pdialog.closeDialog(); return -1; } KTempDir configTempDir; configTempDir.setAutoDelete(true); TQString destDir = "/etc/"; pdialog.setStatusMessage(i18n("Stopping servers...")); // Stop SASL if (controlSASLServer(SC_STOP) != 0) { #ifdef STRICT_SETUP if (errstr) *errstr = i18n("Unable to stop SASL server"); pdialog.closeDialog(); return -1; #endif // STRICT_SETUP } // Stop Heimdal if (controlHeimdalServer(SC_STOP) != 0) { #ifdef STRICT_SETUP if (errstr) *errstr = i18n("Unable to stop Kerberos server"); pdialog.closeDialog(); return -1; #endif // STRICT_SETUP } // Stop slapd if (controlLDAPServer(SC_STOP) != 0) { #ifdef STRICT_SETUP if (errstr) *errstr = i18n("Unable to stop LDAP server"); pdialog.closeDialog(); return -1; #endif // STRICT_SETUP } pdialog.setStatusMessage(i18n("Purging existing LDAP database...")); tqApp->processEvents(); controlHeimdalServer(SC_PURGE); controlLDAPServer(SC_PURGE); pdialog.setStatusMessage(i18n("Installing new LDAP schema...")); tqApp->processEvents(); mkdir(TQString(destDir + "heimdal-kdc").ascii(), S_IRUSR|S_IWUSR|S_IXUSR); mkdir(TQString(destDir + "ldap").ascii(), S_IRUSR|S_IWUSR|S_IXUSR); mkdir(TQString(destDir + "ldap/slapd.d").ascii(), S_IRUSR|S_IWUSR|S_IXUSR); mkdir(TQString(destDir + "ldap/slapd.d/cn=config").ascii(), S_IRUSR|S_IWUSR|S_IXUSR); mkdir(TQString(destDir + "ldap/slapd.d/cn=config/cn=schema").ascii(), S_IRUSR|S_IWUSR|S_IXUSR); mkdir(TDE_CERTIFICATE_DIR, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); mkdir(KERBEROS_PKI_ANCHORDIR, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); mkdir(KERBEROS_PKI_PRIVATEDIR, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); mkdir(KERBEROS_PKI_PUBLICDIR, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); // Heimdal replacePlaceholdersInFile(templateDir + "heimdal/heimdal.defaults", HEIMDAL_DEFAULT_FILE, realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); replacePlaceholdersInFile(templateDir + "heimdal/kadmind.acl", HEIMDAL_ACL_FILE, realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); replacePlaceholdersInFile(templateDir + "heimdal/kdc.conf", destDir + "heimdal-kdc/kdc.conf", realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); replacePlaceholdersInFile(templateDir + "heimdal/krb5.conf", destDir + "krb5.conf", realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); // OpenLDAP replacePlaceholdersInFile(templateDir + "openldap/skel.ldif", configTempDir.name() + "skel.ldif", realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); // replacePlaceholdersInFile(templateDir + "openldap/ldap/slapd.conf", destDir + "ldap/slapd.conf", realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); replacePlaceholdersInFile(templateDir + "openldap/ldap/slapd.defaults", LDAP_DEFAULT_FILE, realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, -1, -1, -1, m_ldapUserName, m_ldapGroupName); // SASL replacePlaceholdersInFile(templateDir + "sasl/saslauthd.defaults", SASL_DEFAULT_FILE, realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); replacePlaceholdersInFile(templateDir + "sasl/slapd.conf", SASL_CONTROL_FILE, realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); // OpenSSL replacePlaceholdersInFile(templateDir + "openssl/pki_extensions", OPENSSL_EXTENSIONS_FILE, realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword); // FIXME // This assumes Debian! // Grant LDAP access to SASL mux pipe system_safe("dpkg-statoverride --remove --quiet /var/run/saslauthd"); system_safe(TQString("dpkg-statoverride --add root %1 710 /var/run/saslauthd").arg(m_ldapGroupName).ascii()); // FIXME // This assumes Debian! system_safe("ln -s /etc/heimdal-kdc/kadmind.acl /var/lib/heimdal-kdc/kadmind.acl"); system_safe("ln -s /etc/heimdal-kdc/kdc.conf /var/lib/heimdal-kdc/kdc.conf"); uid_t slapd_uid = 0; gid_t slapd_gid = 0; // Get LDAP user uid/gid struct passwd *pwd; pwd = getpwnam(m_ldapUserName); slapd_uid = pwd->pw_uid; slapd_gid = pwd->pw_gid; // SECURITY // Make sure that the ldapi:/// socket in /var/run/slapd/ldapi is NOT world readable/writable (technically the permissions are for the directory containing the ldapi socket) // This would mean that anyone with access to the server running LDAP can dump the KRB5 keys! // FIXME // Can we do anything about this now? // Base database configuration replacePlaceholdersInFile(templateDir + "openldap/ldif/config.ldif", destDir + "ldap/slapd.d/" + TQString("cn=config.ldif"), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, -1, slapd_uid, slapd_gid); replacePlaceholdersInFile(templateDir + "openldap/ldif/schema.ldif", destDir + "ldap/slapd.d/cn=config/" + TQString("cn=schema.ldif"), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, -1, slapd_uid, slapd_gid); ldifSchemaNumber = 0; replacePlaceholdersInFile(templateDir + "openldap/ldif/olcConfig.ldif", destDir + "ldap/slapd.d/cn=config/" + TQString("olcDatabase={%1}config.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); replacePlaceholdersInFile(templateDir + "openldap/ldif/moduleConfig.ldif", destDir + "ldap/slapd.d/cn=config/" + TQString("cn=module{%1}.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 1; replacePlaceholdersInFile(templateDir + "openldap/ldif/olcDatabase.ldif", destDir + "ldap/slapd.d/cn=config/" + TQString("olcDatabase={%1}hdb.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); // Schema files ldifSchemaNumber = 0; replacePlaceholdersInFile(templateDir + "openldap/ldif/core.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}core.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 1; replacePlaceholdersInFile(templateDir + "openldap/ldif/cosine.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}cosine.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 2; replacePlaceholdersInFile(templateDir + "openldap/ldif/inetorgperson.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}inetorgperson.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 3; replacePlaceholdersInFile(templateDir + "openldap/ldif/rfc2307bis.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}rfc2307bis.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 4; replacePlaceholdersInFile(templateDir + "openldap/ldif/rfc2739.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}rfc2739.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 5; replacePlaceholdersInFile(templateDir + "openldap/ldif/ppolicy.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}ppolicy.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 6; replacePlaceholdersInFile(templateDir + "openldap/ldif/ems-core.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}ems-core.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 7; replacePlaceholdersInFile(templateDir + "openldap/ldif/hdb.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}hdb.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); ldifSchemaNumber = 8; replacePlaceholdersInFile(templateDir + "openldap/ldif/tde-core.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}tde-core.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); // ldifSchemaNumber = 9; // replacePlaceholdersInFile(templateDir + "openldap/ldif/samba.ldif", destDir + "ldap/slapd.d/cn=config/cn=schema/" + TQString("cn={%1}samba.ldif").arg(ldifSchemaNumber), realmconfig, adminUserName, adminGroupName, machineAdminGroupName, standardUserGroupName, adminPassword, rootUserName, rootPassword, ldifSchemaNumber, slapd_uid, slapd_gid); // Set permissions chmod(TQString(HEIMDAL_DEFAULT_FILE).ascii(), S_IRUSR|S_IWUSR|S_IRGRP); chmod(TQString(HEIMDAL_ACL_FILE).ascii(), S_IRUSR|S_IWUSR|S_IRGRP); chown_safe(TQString(HEIMDAL_ACL_FILE).ascii(), slapd_uid, 0); chmod(TQString(destDir + "heimdal-kdc/kdc.conf").ascii(), S_IRUSR|S_IWUSR|S_IRGRP); chmod(TQString(destDir + "krb5.conf").ascii(), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chmod(TQString(configTempDir.name() + "skel.ldif").ascii(), S_IRUSR|S_IWUSR); // chmod(TQString(destDir + "ldap/slapd.conf").ascii(), S_IRUSR|S_IWUSR); chmod(TQString(LDAP_DEFAULT_FILE).ascii(), S_IRUSR|S_IWUSR|S_IRGRP); chmod(TQString(SASL_DEFAULT_FILE).ascii(), S_IRUSR|S_IWUSR|S_IRGRP); chmod(TQString(SASL_CONTROL_FILE).ascii(), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chmod(TQString(OPENSSL_EXTENSIONS_FILE).ascii(), S_IRUSR|S_IWUSR); pdialog.setStatusMessage(i18n("Installing realm certificates...")); tqApp->processEvents(); if (certinfo.generate_certs) { // Generate certificates if (createRealmCertificates(certinfo, realmconfig, slapd_uid, slapd_gid) != 0) { if (errstr) *errstr = i18n("Unable to install realm certificates"); pdialog.closeDialog(); return -1; } m_certconfig = certinfo; } else { // Copy certificates TQString kdc_certfile = KERBEROS_PKI_KDC_FILE; TQString kdc_keyfile = KERBEROS_PKI_KDCKEY_FILE; kdc_certfile.replace("@@@KDCSERVER@@@", realmconfig.kdc); kdc_keyfile.replace("@@@KDCSERVER@@@", realmconfig.kdc); TQString ldap_certfile = LDAP_CERT_FILE; TQString ldap_keyfile = LDAP_CERTKEY_FILE; ldap_certfile.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); ldap_keyfile.replace("@@@ADMINSERVER@@@", realmconfig.admin_server); // Copy files // FIXME // There has GOT to be a better way to do this than system()!!! TQString command; command = TQString("cp %1 %2").arg(certinfo.provided_kerberos_pem).arg(KERBEROS_PKI_PEMKEY_FILE); system_safe(command); command = TQString("cp %1 %2").arg(certinfo.provided_kerberos_pemkey).arg(KERBEROS_PKI_PEM_FILE); system_safe(command); command = TQString("cp %1 %2").arg(certinfo.provided_kerberos_crt).arg(kdc_certfile); system_safe(command); command = TQString("cp %1 %2").arg(certinfo.provided_kerberos_key).arg(kdc_keyfile); system_safe(command); command = TQString("cp %1 %2").arg(certinfo.provided_ldap_crt).arg(ldap_certfile); system_safe(command); command = TQString("cp %1 %2").arg(certinfo.provided_ldap_key).arg(ldap_keyfile); system_safe(command); // Set permissions chmod(KERBEROS_PKI_PEMKEY_FILE, S_IRUSR|S_IWUSR); chown_safe(KERBEROS_PKI_PEMKEY_FILE, 0, 0); chmod(KERBEROS_PKI_PEM_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown_safe(KERBEROS_PKI_PEM_FILE, 0, 0); chmod(kdc_keyfile.ascii(), S_IRUSR|S_IWUSR); chown_safe(kdc_keyfile.ascii(), 0, 0); chmod(kdc_certfile.ascii(), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown_safe(kdc_certfile.ascii(), 0, 0); chmod(ldap_keyfile.ascii(), S_IRUSR|S_IWUSR); chown_safe(ldap_keyfile.ascii(), slapd_uid, slapd_gid); chmod(ldap_certfile.ascii(), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown_safe(ldap_certfile.ascii(), slapd_uid, slapd_gid); } pdialog.setStatusMessage(i18n("Loading initial database into LDAP...")); tqApp->processEvents(); // Load database TDEProcess slapadd; slapadd << "slapadd" << "-l" << configTempDir.name() + "skel.ldif"; slapadd.start(); while (slapadd.isRunning()) { tqApp->processEvents(); } if (slapadd.exitStatus() != 0) { if (errstr) *errstr = i18n("Unable to import initial database into LDAP"); pdialog.closeDialog(); return -1; } controlLDAPServer(SC_SETDBPERMS, slapd_uid, slapd_gid); pdialog.setStatusMessage(i18n("Starting servers...")); tqApp->processEvents(); // Start slapd if (controlLDAPServer(SC_START) != 0) { if (errstr) *errstr = i18n("Unable to start LDAP server"); pdialog.closeDialog(); return -1; } // Start Heimdal if (controlHeimdalServer(SC_START) != 0) { if (errstr) *errstr = i18n("Unable to start Kerberos server"); pdialog.closeDialog(); return -1; } pdialog.setStatusMessage(i18n("Initializing Kerberos database...")); tqApp->processEvents(); TQString errorstring; if (initializeNewKerberosRealm(realmconfig.name.upper(), &errorstring) != 0) { if (errstr) *errstr = i18n("Unable to initialize Kerberos database

").append(errorstring); pdialog.closeDialog(); return -1; } if (addHostEntryToKerberosRealm(realmconfig.kdc, &errorstring) != 0) { if (errstr) *errstr = i18n("Unable to add KDC server entry to Kerberos database

").append(errorstring); pdialog.closeDialog(); return -1; } if (addLDAPEntryToKerberosRealm(m_ldapUserName, realmconfig.admin_server, &errorstring) != 0) { if (errstr) *errstr = i18n("Unable to add %1 entry to Kerberos database

").arg(m_ldapUserName).append(errorstring); pdialog.closeDialog(); return -1; } if (addLDAPEntryToKerberosRealm("ldap", realmconfig.admin_server, &errorstring) != 0) { if (errstr) *errstr = i18n("Unable to add LDAP entry to Kerberos database

").append(errorstring); pdialog.closeDialog(); return -1; } controlHeimdalServer(SC_SETDBPERMS, slapd_uid, slapd_gid); // Move all those new Heimdal entries to the correct tree/branch TQStringList domainChunks = TQStringList::split(".", realmconfig.name.lower()); TQString basedcname = "dc=" + domainChunks.join(",dc="); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmconfig.name.upper(); LDAPManager* ldap_mgr = new LDAPManager(realmconfig.name.upper(), "ldapi://", credentials); if (ldap_mgr->moveKerberosEntries("o=kerberos,cn=kerberos control,ou=master services,ou=core,ou=realm," + basedcname, &errorstring) != 0) { delete ldap_mgr; delete credentials; if (errstr) *errstr = errorstring; pdialog.closeDialog(); return -1; } // Set CA master if (ldap_mgr->setRealmCAMaster(m_fqdn, &errorstring) != 0) { delete ldap_mgr; delete credentials; if (errstr) *errstr = errorstring; pdialog.closeDialog(); return -1; } // Upload the contents of KERBEROS_PKI_PEM_FILE to the LDAP server if (uploadKerberosCAFileToLDAP(ldap_mgr, &errorstring) != 0) { delete ldap_mgr; delete credentials; if (errstr) *errstr = errorstring; pdialog.closeDialog(); return -1; } // Upload the contents of KERBEROS_PKI_PEMKEY_FILE to the LDAP server if (uploadKerberosCAKeyFileToLDAP(ldap_mgr, &errorstring) != 0) { delete ldap_mgr; delete credentials; if (errstr) *errstr = errorstring; pdialog.closeDialog(); return -1; } // Set @@@ADMINUSER@@@ password in kadmin LDAPCredentials adminuser; adminuser.username = adminUserName; adminuser.password = adminPassword; adminuser.realm = realmconfig.name.upper(); if (setKerberosPasswordForUser(adminuser, &errorstring) != 0) { delete ldap_mgr; delete credentials; if (errstr) *errstr = i18n("Unable to set user password in Kerberos database

").append(errorstring); pdialog.closeDialog(); return -1; } pdialog.setStatusMessage(i18n("Configuring local system...")); tqApp->processEvents(); // Write the TDE realm configuration file LDAPRealmConfigList realms; realms.insert(realmconfig.name, realmconfig); LDAPManager::writeTDERealmList(realms, m_systemconfig); m_systemconfig->setGroup(NULL); m_systemconfig->writeEntry("DefaultRealm", realmconfig.name); m_systemconfig->setGroup("Replication"); m_systemconfig->writeEntry("Password", adminPassword); m_systemconfig->setGroup(NULL); m_systemconfig->sync(); LDAPManager::writeLDAPConfFile(realmconfig); // Write the sudoers file if (ldap_mgr->writeSudoersConfFile(&errorstring) != 0) { delete ldap_mgr; delete credentials; if (errstr) *errstr = i18n("Unable to set local sudo rights

").append(errorstring); pdialog.closeDialog(); return -1; } LDAPManager::writePrimaryRealmCertificateUpdateCronFile(); delete ldap_mgr; delete credentials; pdialog.setStatusMessage(i18n("(Re)starting servers...")); tqApp->processEvents(); // Restart slapd if (controlLDAPServer(SC_RESTART) != 0) { if (errstr) *errstr = i18n("Unable to restart LDAP server"); pdialog.closeDialog(); return -1; } // Restart Heimdal if (controlHeimdalServer(SC_RESTART) != 0) { if (errstr) *errstr = i18n("Unable to restart Kerberos server"); pdialog.closeDialog(); return -1; } // Restart kadmind if (controlKAdminDaemon(SC_RESTART) != 0) { if (errstr) *errstr = i18n("Unable to restart Kerberos Administration Service"); pdialog.closeDialog(); return -1; } // Start SASL if (controlSASLServer(SC_START) != 0) { if (errstr) *errstr = i18n("Unable to start SASL server"); pdialog.closeDialog(); return -1; } // Write the NSS update crontab file and update NSS database LDAPManager::writeClientCronFiles(); pdialog.closeDialog(); return 0; } int LDAPController::buttons() { return TDECModule::Apply|TDECModule::Help; } TQString LDAPController::quickHelp() const { return i18n("This module configures an LDAP Realm Controller."); }