/*************************************************************************** * 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 <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <pwd.h> #include <tqlayout.h> #include <klocale.h> #include <kglobal.h> #include <kparts/genericfactory.h> #include <ksimpleconfig.h> #include <kglobalsettings.h> #include <kstandarddirs.h> #include <kurlrequester.h> #include <klistview.h> #include <kopenwith.h> #include <kpropertiesdialog.h> #include <kio/job.h> #include <tqdir.h> #include <tqheader.h> #include <kcombobox.h> #include <kmessagebox.h> #include <tqcheckbox.h> #include <ktempdir.h> #include <kprocess.h> #include <tdesu/process.h> #include <libtdeldap.h> #include <kfiledialog.h> #include <kpassdlg.h> #include "sha1.h" #include "ldapcontroller.h" #include "primaryrealmwizard/realmwizard.h" #include "processingdialog.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 // RAJA FIXME // Certificate manager/updater (CLI, callable from crontab) still needs to be written... typedef KGenericFactory<LDAPController, TQWidget> ldapFactory; K_EXPORT_COMPONENT_FACTORY( kcm_ldapcontroller, ldapFactory("kcmldapcontroller")) LDAPController::LDAPController(TQWidget *parent, const char *name, const TQStringList&) : KCModule(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); KAboutData* about = new KAboutData("ldapcontroller", I18N_NOOP("TDE LDAP Controller"), "0.1", I18N_NOOP("TDE LDAP Controller Control Panel Module"), KAboutData::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); setRootOnlyMsg(i18n("<b>LDAP controller settings take effect system wide, and require administrator access to modify</b><br>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->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())); m_fqdn = LDAPManager::getMachineFQDN(); // FIXME // This assumes Debian! m_ldapUserName = "openldap"; m_ldapGroupName = "openldap"; load(); processLockouts(); }; LDAPController::~LDAPController() { } void LDAPController::systemRoleChanged() { if (m_base->systemRole->currentItem() != m_prevRole) { if (m_base->systemRole->currentItem() == ROLE_PRIMARY_REALM_CONTROLLER) { // 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 (bonded) { KMessageBox::error(0, i18n("<qt>You are already bonded to a realm!<p>Please unbond from all realms before selecting a Realm Controller role</qt>"), i18n("Common Sense Failure")); m_base->systemRole->setCurrentItem(0); } else { // Something will probably change save(); RealmWizard realmwizard(this, m_fqdn, m_certconfig, this); if (realmwizard.exec() < 0) { // Wizard was cancelled // Back out all changes! m_base->systemRole->setCurrentItem(ROLE_WORKSTATION); save(); } else { // Wizard completed; commit changes save(); } // Something probably changed load(); } } else if (m_base->systemRole->currentItem() == ROLE_SECONDARY_REALM_CONTROLLER) { // RAJA FIXME KMessageBox::error(0, i18n("<qt>Secondary realm controller support is not yet available<p>If you want to see it implemented, contact the Trinity Desktop developers</qt>"), i18n("Feature Not Yet Available")); m_base->systemRole->setCurrentItem(m_prevRole); } else if (m_base->systemRole->currentItem() == ROLE_WORKSTATION) { if (KMessageBox::warningYesNo(this, i18n("<qt><b>WARNING</b><br>You are attempting to demote a realm controller<p>This action will <b>PERMANENTLY DESTROY</b> the realm directory stored on this machine<p>If you do not want to do this, select <b>Cancel</b> below</qt>"), 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(TQString("rm -rf %1").arg(TDE_CERTIFICATE_DIR)); // Write the TDE realm configuration file LDAPRealmConfigList realms; LDAPManager::writeTDERealmList(realms, m_systemconfig); m_systemconfig->deleteEntry("DefaultRealm"); m_systemconfig->sync(); pdialog.closeDialog(); load(); } else { m_base->systemRole->setCurrentItem(m_prevRole); } } } } void LDAPController::processLockouts() { bool enabled = true; bool canChangeLDAPEnabled = true; if (getuid() != 0 || !m_systemconfig->checkConfigFilesWritable( true )) { canChangeLDAPEnabled = false; enabled = false; } if (m_base->systemRole->currentItem() != ROLE_WORKSTATION) { canChangeLDAPEnabled = 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 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) { 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 other instance of locked "admin" in realmwizard.cpp ::accept() m_base->ldapRootUser->setText(TQString("cn=%1,").arg("admin") + LDAPManager::ldapdnForRealm(m_defaultRealm)); 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); 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)); updateCertDisplay(); m_certRefreshTimer.start(60*1000); } else { 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::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("<qt>Unable to upload new certificate to LDAP server!<p>%1</qt>").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()) { KIO::CopyJob* job = KIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(slotCertCopyResult(KIO::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()) { KIO::CopyJob* job = KIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(slotCertCopyResult(KIO::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()) { KIO::CopyJob* job = KIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(slotCertCopyResult(KIO::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()) { KIO::CopyJob* job = KIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(slotCertCopyResult(KIO::Job*))); } } void LDAPController::btnldapRegenerate() { struct stat sb; 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()) { KIO::CopyJob* job = KIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(slotCertCopyResult(KIO::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()) { KIO::CopyJob* job = KIO::copy(src, dest, true); connect(job, TQT_SIGNAL(result(KIO::Job*)), this, TQT_SLOT(slotCertCopyResult(KIO::Job*))); } } void LDAPController::slotCertCopyResult(KIO::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("<qt>Unable to modify LDAP root password<p>Your LDAP server may now be in an inconsistent or disabled state</qt>"), 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); } delete ldap_mgr; delete credentials; } } void LDAPController::defaults() { // } void LDAPController::save() { 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 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(); 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 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("@@@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(outfile.ascii(), userid, groupid); } } else { //KMessageBox::error(0, i18n("<qt>Unable to open output schema file %1 for writing</qt>").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("<qt>Unable to open template schema file %1</qt>").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"); } } 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"); } } 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("rm -f " + TQString(LDAP_KEYTAB_FILE)); // FIXME // This assumes Debian system("rm -f /etc/krb5.keytab"); system("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(command.ascii()); chmod(LDAP_KEYTAB_FILE, S_IRUSR|S_IWUSR|S_IRGRP); } } } 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("rm -rf /var/lib/ldap/*"); system("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(command.ascii()); command = TQString("chgrp -R %1 /var/lib/ldap/*").arg(groupid); system(command.ascii()); command = TQString("chown -R %1 /etc/ldap/slapd.d/*").arg(userid); system(command.ascii()); command = TQString("chgrp -R %1 /etc/ldap/slapd.d/*").arg(groupid); system(command.ascii()); } } return -2; } TQString readFullLineFromPtyProcess(PtyProcess* proc) { TQString result = ""; while ((!result.contains("\n")) && (!result.contains(":")) && (!result.contains(">"))) { result = result + TQString(proc->readLine(false)); tqApp->processEvents(); } return result; } int LDAPController::initializeNewKerberosRealm(TQString realmName, TQString *errstr) { TQCString command = "kadmin"; QCStringList args; args << TQCString("-l"); TQString prompt; PtyProcess kadminProc; kadminProc.exec(command, args); prompt = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { kadminProc.writeLine(TQCString("init "+realmName), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } else if (prompt.startsWith("Realm max")) { kadminProc.writeLine("unlimited", true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt.startsWith("Realm max")) { kadminProc.writeLine("unlimited", true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); } if (prompt != "kadmin>") { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = prompt; 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 = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { kadminProc.writeLine(TQCString("ext "+hoststring), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } else if (prompt.endsWith("Principal does not exist")) { kadminProc.writeLine(TQCString("ank --random-key "+hoststring), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); // Use all defaults while (prompt != "kadmin>") { if (prompt.contains("authentication failed")) { if (errstr) *errstr = prompt; 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); } kadminProc.writeLine(TQCString(defaultParam), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); } } kadminProc.writeLine(TQCString("ext "+hoststring), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt != "kadmin>") { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.writeLine("quit", true); return 0; } else if (prompt == "kadmin>") { // Success! kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = prompt; 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 = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { kadminProc.writeLine(TQCString("ext --keytab="+TQString(LDAP_KEYTAB_FILE)+" "+hoststring), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } else if (prompt.endsWith("Principal does not exist")) { kadminProc.writeLine(TQCString("ank --random-key "+hoststring), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); // Use all defaults while (prompt != "kadmin>") { if (prompt.contains("authentication failed")) { if (errstr) *errstr = prompt; 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); } kadminProc.writeLine(TQCString(defaultParam), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); } } kadminProc.writeLine(TQCString("ext --keytab="+TQString(LDAP_KEYTAB_FILE)+" "+hoststring), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt != "kadmin>") { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.writeLine("quit", true); return 0; } else if (prompt == "kadmin>") { // Success! kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = prompt; 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 = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); if (prompt == "kadmin>") { kadminProc.writeLine(TQCString("passwd "+user.username), true); prompt = kadminProc.readLine(true); // Discard our own input prompt = readFullLineFromPtyProcess(&kadminProc); prompt = prompt.stripWhiteSpace(); if (prompt.contains("authentication failed")) { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } else if ((prompt.endsWith(" Password:")) && (prompt.startsWith(TQString(user.username + "@")))) { kadminProc.writeLine(user.password, true); prompt = kadminProc.readLine(true); // Discard our own input prompt = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); if ((prompt.endsWith(" Password:")) && (prompt.startsWith("Verify"))) { kadminProc.writeLine(user.password, true); prompt = kadminProc.readLine(true); // Discard our own input prompt = kadminProc.readLine(true); prompt = prompt.stripWhiteSpace(); } if (prompt != "kadmin>") { if (errstr) *errstr = prompt; kadminProc.writeLine("quit", true); return 1; } // Success! kadminProc.writeLine("quit", true); return 0; } else if (prompt == "kadmin>") { // Success! kadminProc.writeLine("quit", true); return 0; } // Failure if (errstr) *errstr = prompt; 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(command); chmod(KERBEROS_PKI_PEMKEY_FILE, S_IRUSR|S_IWUSR); chown(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(command); chmod(kdc_keyfile.ascii(), S_IRUSR|S_IWUSR); chown(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(command); chmod(ldap_keyfile.ascii(), S_IRUSR|S_IWUSR); chown(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::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) { int ldifSchemaNumber; ProcessingDialog pdialog(dialogparent); pdialog.setStatusMessage(i18n("Loading data for realm deployment...")); pdialog.raise(); pdialog.setActiveWindow(); tqApp->processEvents(); // RAJA 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("dpkg-statoverride --remove --quiet /var/run/saslauthd"); system(TQString("dpkg-statoverride --add root %1 710 /var/run/saslauthd").arg(m_ldapGroupName).ascii()); // FIXME // This assumes Debian! system("ln -s /etc/heimdal-kdc/kadmind.acl /var/lib/heimdal-kdc/kadmind.acl"); system("ln -s /etc/heimdal-kdc/kdc.conf /var/lib/heimdal-kdc/kdc.conf"); struct stat sb; 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(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(command); command = TQString("cp %1 %2").arg(certinfo.provided_kerberos_pemkey).arg(KERBEROS_PKI_PEM_FILE); system(command); command = TQString("cp %1 %2").arg(certinfo.provided_kerberos_crt).arg(kdc_certfile); system(command); command = TQString("cp %1 %2").arg(certinfo.provided_kerberos_key).arg(kdc_keyfile); system(command); command = TQString("cp %1 %2").arg(certinfo.provided_ldap_crt).arg(ldap_certfile); system(command); command = TQString("cp %1 %2").arg(certinfo.provided_ldap_key).arg(ldap_keyfile); system(command); // Set permissions chmod(KERBEROS_PKI_PEMKEY_FILE, S_IRUSR|S_IWUSR); chown(KERBEROS_PKI_PEMKEY_FILE, 0, 0); chmod(KERBEROS_PKI_PEM_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown(KERBEROS_PKI_PEM_FILE, 0, 0); chmod(kdc_keyfile.ascii(), S_IRUSR|S_IWUSR); chown(kdc_keyfile.ascii(), 0, 0); chmod(kdc_certfile.ascii(), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown(kdc_certfile.ascii(), 0, 0); chmod(ldap_keyfile.ascii(), S_IRUSR|S_IWUSR); chown(ldap_keyfile.ascii(), slapd_uid, slapd_gid); chmod(ldap_certfile.ascii(), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown(ldap_certfile.ascii(), slapd_uid, slapd_gid); } pdialog.setStatusMessage(i18n("Loading initial database into LDAP...")); tqApp->processEvents(); // Load database KProcess 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").arg(m_ldapUserName).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; } // 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->writeEntry("DefaultRealm", realmconfig.name); 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; } 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::writeCronFiles(); // RAJA FIXME pdialog.closeDialog(); } int LDAPController::buttons() { return KCModule::Apply|KCModule::Help; } TQString LDAPController::quickHelp() const { return i18n("This module configures an LDAP Realm Controller."); }