/*************************************************************************** * Copyright (C) 2012-2013 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 "tdeumaskinput.h" #include "ldapbonding.h" #include "bondwizard.h" #include "ldappasswddlg.h" #include "realmpropertiesdialog.h" // FIXME // Connect this to CMake/Automake #define KDE_CONFDIR "/etc/trinity" typedef KGenericFactory ldapFactory; K_EXPORT_COMPONENT_FACTORY( kcm_ldapbonding, ldapFactory("kcmldapbonding")) KSimpleConfig *systemconfig = 0; LDAPConfig::LDAPConfig(TQWidget *parent, const char *name, const TQStringList&) : TDECModule(parent, name), myAboutData(0) { TQVBoxLayout *layout = new TQVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint()); systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" )); systemconfig->setFileWriteMode(S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); TDEAboutData* about = new TDEAboutData("ldap", I18N_NOOP("TDE LDAP Manager"), "0.1", I18N_NOOP("TDE LDAP Manager Control Panel Module"), TDEAboutData::License_GPL, I18N_NOOP("(c) 2012-2013 Timothy Pearson"), 0, 0); about->addAuthor("Timothy Pearson", 0, "kb9vqf@pearsoncomputing.net"); setAboutData( about ); base = new LDAPConfigBase(this); layout->add(base); base->ldapRealmList->setAllColumnsShowFocus(true); base->ldapRealmList->setFullWidth(true); setRootOnlyMsg(i18n("Bonded LDAP realms take effect system wide, and require administrator access to modify
To alter the system's bonded LDAP realms, click on the \"Administrator Mode\" button below.")); setUseRootOnlyMsg(true); connect(base->systemEnableSupport, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed())); connect(base->defaultRealm, TQT_SIGNAL(activated(int)), this, TQT_SLOT(changed())); connect(base->ticketLifetime, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); connect(base->systemEnableSupport, TQT_SIGNAL(clicked()), this, TQT_SLOT(processLockouts())); connect(base->ldapRealmList, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(processLockouts())); connect(base->btnBondRealm, TQT_SIGNAL(clicked()), this, TQT_SLOT(bondToNewRealm())); connect(base->btnReBondRealm, TQT_SIGNAL(clicked()), this, TQT_SLOT(reBondToRealm())); connect(base->btnRemoveRealm, TQT_SIGNAL(clicked()), this, TQT_SLOT(removeRealm())); connect(base->btnDeactivateRealm, TQT_SIGNAL(clicked()), this, TQT_SLOT(deactivateRealm())); connect(base->btnRealmProperties, TQT_SIGNAL(clicked()), this, TQT_SLOT(realmProperties())); connect(base->ldapVersion, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); connect(base->ldapTimeout, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); connect(base->bindPolicy, TQT_SIGNAL(activated(int)), this, TQT_SLOT(changed())); connect(base->ldapBindTimeout, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); connect(base->passwordHash, TQT_SIGNAL(activated(int)), this, TQT_SLOT(changed())); connect(base->ignoredUsers, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(changed())); connect(base->pamEnableCachedLogons, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed())); connect(base->pamCreateHomeDirectory, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed())); connect(base->pamCreateHomeDirectory, TQT_SIGNAL(clicked()), this, TQT_SLOT(processLockouts())); connect(base->pamCreateHomeDirectoryUmask, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed())); connect(base->pamCreateHomeDirectorySkelDir, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(changed())); hostFQDN = LDAPManager::getMachineFQDN(); base->hostFQDN->setEnabled(false); base->hostFQDN->clear(); base->hostFQDN->insertItem(hostFQDN); load(); systemconfig->setGroup(NULL); if ((getuid() != 0) || (!systemconfig->checkConfigFilesWritable( true )) || (m_clientRealmConfig.ldapRole != "Workstation")) { base->systemEnableSupport->setEnabled(false); } processLockouts(); }; LDAPConfig::~LDAPConfig() { delete systemconfig; } void LDAPConfig::load() { kgs = new TDEGlobalSettings(); load(false); } void LDAPConfig::load(bool useDefaults ) { int i; m_clientRealmConfig = LDAPManager::loadClientRealmConfig(systemconfig, useDefaults); base->systemEnableSupport->setChecked(m_clientRealmConfig.enable_bonding); // Load realms m_realms.clear(); m_realms = LDAPManager::readTDERealmList(systemconfig, !m_clientRealmConfig.configurationVerifiedForLocalMachine); base->ticketLifetime->setValue(m_clientRealmConfig.ticketLifetime); base->ldapVersion->setValue(m_clientRealmConfig.ldapVersion); base->ldapTimeout->setValue(m_clientRealmConfig.ldapTimeout); for (i=0; ibindPolicy->count(); i++) { if (base->bindPolicy->text(i).lower() == m_clientRealmConfig.defaultRealm.lower()) { base->bindPolicy->setCurrentItem(i); break; } } base->ldapBindTimeout->setValue(m_clientRealmConfig.ldapBindTimeout); for (i=0; ipasswordHash->count(); i++) { if (base->passwordHash->text(i).lower() == m_clientRealmConfig.passwordHash.lower()) { base->passwordHash->setCurrentItem(i); break; } } base->ignoredUsers->setText(m_clientRealmConfig.ignoredUsers); base->pamEnableCachedLogons->setChecked(m_clientRealmConfig.pamConfig.enable_cached_credentials); base->pamCreateHomeDirectory->setChecked(m_clientRealmConfig.pamConfig.autocreate_user_directories_enable); base->pamCreateHomeDirectoryUmask->setValue(m_clientRealmConfig.pamConfig.autocreate_user_directories_umask); base->pamCreateHomeDirectorySkelDir->setURL(m_clientRealmConfig.pamConfig.autocreate_user_directories_skel); updateRealmList(); processLockouts(); emit changed(useDefaults); } void LDAPConfig::updateRealmList() { base->ldapRealmList->clear(); base->defaultRealm->clear(); LDAPRealmConfigList::Iterator it; for (it = m_realms.begin(); it != m_realms.end(); ++it) { LDAPRealmConfig realmcfg = it.data(); (void)new TQListViewItem(base->ldapRealmList, ((realmcfg.bonded)?i18n("Bonded"):i18n("Deactivated")), realmcfg.name); base->defaultRealm->insertItem(realmcfg.name); } if (m_clientRealmConfig.defaultRealm != "") { for (int i=0; idefaultRealm->count(); i++) { if (base->defaultRealm->text(i) == m_clientRealmConfig.defaultRealm) { base->defaultRealm->setCurrentItem(i); break; } } } processLockouts(); } void LDAPConfig::defaults() { } void LDAPConfig::save() { TQString errorstring; m_clientRealmConfig.hostFQDN = hostFQDN; m_clientRealmConfig.enable_bonding = base->systemEnableSupport->isChecked(); m_clientRealmConfig.defaultRealm = base->defaultRealm->currentText(); m_clientRealmConfig.ticketLifetime = base->ticketLifetime->value(); m_clientRealmConfig.ldapVersion = base->ldapVersion->value(); m_clientRealmConfig.ldapTimeout = base->ldapTimeout->value(); m_clientRealmConfig.bindPolicy = base->bindPolicy->currentText(); m_clientRealmConfig.ldapBindTimeout = base->ldapBindTimeout->value(); m_clientRealmConfig.passwordHash = base->passwordHash->currentText(); m_clientRealmConfig.ignoredUsers = base->ignoredUsers->text(); m_clientRealmConfig.pamConfig.enable_cached_credentials = base->pamEnableCachedLogons->isChecked(); m_clientRealmConfig.pamConfig.autocreate_user_directories_enable = base->pamCreateHomeDirectory->isChecked(); m_clientRealmConfig.pamConfig.autocreate_user_directories_umask = base->pamCreateHomeDirectoryUmask->value(); m_clientRealmConfig.pamConfig.autocreate_user_directories_skel = base->pamCreateHomeDirectorySkelDir->url(); // Write system configuration if (LDAPManager::saveClientRealmConfig(m_clientRealmConfig, systemconfig, &errorstring) != 0) { KMessageBox::error(this, i18n("Unable to save configuration!

Details: %2").arg(errorstring), i18n("Unable to Save Configuration")); return; } LDAPManager::writeTDERealmList(m_realms, systemconfig); systemconfig->sync(); if (m_clientRealmConfig.enable_bonding) { // Write the Kerberos5 configuration file if (LDAPManager::writeClientKrb5ConfFile(m_clientRealmConfig, m_realms, &errorstring) != 0) { KMessageBox::error(this, i18n("Unable to save configuration!

Details: %2").arg(errorstring), i18n("Unable to Save Configuration")); return; } // Write the LDAP configuration file if (LDAPManager::writeLDAPConfFile(m_realms[m_clientRealmConfig.defaultRealm], &errorstring) != 0) { KMessageBox::error(this, i18n("Unable to save configuration!

Details: %2").arg(errorstring), i18n("Unable to Save Configuration")); return; } // Write the NSSwitch configuration file if (LDAPManager::writeNSSwitchFile(&errorstring) != 0) { KMessageBox::error(this, i18n("Unable to save configuration!

Details: %2").arg(errorstring), i18n("Unable to Save Configuration")); return; } // Write the PAM configuration files if (LDAPManager::writePAMFiles(m_clientRealmConfig.pamConfig, &errorstring) != 0) { KMessageBox::error(this, i18n("Unable to save configuration!

Details: %2").arg(errorstring), i18n("Unable to Save Configuration")); return; } // Write the cron files if (LDAPManager::writeClientCronFiles() != 0) { KMessageBox::error(this, i18n("Unable to save configuration!

Details: %2").arg(errorstring), i18n("Unable to Save Configuration")); return; } if (m_clientRealmConfig.defaultRealm != "") { // Bind anonymously to LDAP LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = m_clientRealmConfig.defaultRealm.upper(); credentials->use_tls = false; LDAPManager* ldap_mgr = new LDAPManager(m_clientRealmConfig.defaultRealm.upper(), TQString("ldap://%1").arg(m_realms[m_clientRealmConfig.defaultRealm].admin_server).ascii(), credentials); // Add the domain-wide computer local admin group to local sudoers ldap_mgr->writeSudoersConfFile(&errorstring); // Get and install the CA root certificate from LDAP mkdir(TDE_CERTIFICATE_DIR, 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); if (ldap_mgr->getTDECertificate("publicRootCertificate", KERBEROS_PKI_PUBLICDIR + m_realms[m_clientRealmConfig.defaultRealm].admin_server + ".ldap.crt", &errorstring) != 0) { KMessageBox::sorry(this, i18n("Unable to obtain root certificate for realm %1!

Details: %2").arg(m_clientRealmConfig.defaultRealm.upper()).arg(errorstring), i18n("Unable to Obtain Certificate")); } delete ldap_mgr; delete credentials; } // Certificates may have changed; force the certificate update daemon to reload its configuration pid_t certUpdaterPID; TQFile pidFile(TDE_LDAP_CERT_UPDATER_PID_FILE); if (pidFile.open(IO_ReadOnly)) { TQTextStream stream(&pidFile); stream >> certUpdaterPID; pidFile.close(); kill(certUpdaterPID, SIGHUP); } } load(); } void LDAPConfig::processLockouts() { bool panelIsEnabled = (base->systemEnableSupport->isEnabled() && base->systemEnableSupport->isChecked()); base->groupRealms->setEnabled(panelIsEnabled); base->groupKrbDefaults->setEnabled(panelIsEnabled); base->groupConnectionParameters->setEnabled(panelIsEnabled); base->groupPamConfig->setEnabled(panelIsEnabled); TQListViewItem *selrealm = base->ldapRealmList->selectedItem(); if (selrealm) { LDAPRealmConfig realmcfg = m_realms[selrealm->text(1)]; base->btnBondRealm->setEnabled(true); base->btnReBondRealm->setEnabled(true); if (realmcfg.bonded) { base->btnDeactivateRealm->setEnabled(true); base->btnRemoveRealm->setEnabled(false); base->btnRealmProperties->setEnabled(false); } else { base->btnDeactivateRealm->setEnabled(false); base->btnRemoveRealm->setEnabled(true); base->btnRealmProperties->setEnabled(true); } } else { base->btnBondRealm->setEnabled(true); base->btnReBondRealm->setEnabled(false); base->btnDeactivateRealm->setEnabled(false); base->btnRemoveRealm->setEnabled(false); base->btnRealmProperties->setEnabled(false); } if (base->pamCreateHomeDirectory->isChecked()) { base->pamCreateHomeDirectoryUmask->setEnabled(true); base->pamCreateHomeDirectorySkelDir->setEnabled(true); } else { base->pamCreateHomeDirectoryUmask->setEnabled(false); base->pamCreateHomeDirectorySkelDir->setEnabled(false); } } void LDAPConfig::bondToNewRealm() { // Something will probably change save(); BondWizard bondwizard(&m_realms, this, this); bondwizard.exec(); // Something probably changed load(); } void LDAPConfig::reBondToRealm() { TQListViewItem *selrealm = base->ldapRealmList->selectedItem(); if (selrealm) { TQString realmName = selrealm->text(1); LDAPRealmConfig realmcfg = m_realms[realmName]; // Password prompt... TQString errorString; LDAPPasswordDialog passdlg(this); passdlg.m_base->ldapAdminRealm->setEnabled(false); passdlg.m_base->ldapAdminRealm->setText(realmName); if (passdlg.exec() == TQDialog::Accepted) { setEnabled(false); if (LDAPManager::unbondRealm(m_realms[realmName], passdlg.m_base->ldapAdminUsername->text(), passdlg.m_base->ldapAdminPassword->password(), passdlg.m_base->ldapAdminRealm->text(), &errorString) == 0) { // Success! realmcfg.bonded = false; m_realms.remove(realmName); m_realms.insert(realmName, realmcfg); save(); if (LDAPManager::bondRealm(passdlg.m_base->ldapAdminUsername->text(), passdlg.m_base->ldapAdminPassword->password(), passdlg.m_base->ldapAdminRealm->text(), &errorString) == 0) { // Success! realmcfg.bonded = true; m_realms.remove(realmName); m_realms.insert(realmName, realmcfg); save(); } else { KMessageBox::error(this, i18n("Unable to bond to realm!

Details: %1").arg(errorString), i18n("Unable to Bond to Realm")); } } else { KMessageBox::error(this, i18n("Unable to unbond from realm!

%1").arg(errorString), i18n("Unable to Unbond from Realm")); } setEnabled(true); } } updateRealmList(); } void LDAPConfig::removeRealm() { TQListViewItem *selrealm = base->ldapRealmList->selectedItem(); if (selrealm) { m_realms.remove(selrealm->text(1)); updateRealmList(); changed(); } } void LDAPConfig::deactivateRealm() { TQListViewItem *selrealm = base->ldapRealmList->selectedItem(); if (selrealm) { TQString realmName = selrealm->text(1); LDAPRealmConfig realmcfg = m_realms[realmName]; if (realmcfg.bonded == true) { // Password prompt... TQString errorString; LDAPPasswordDialog passdlg(this); passdlg.m_base->ldapAdminRealm->setEnabled(false); passdlg.m_base->ldapAdminRealm->setText(realmName); passdlg.m_base->passprompt->setText(i18n("Please provide LDAP realm administrator credentials below to complete the unbonding process")); if (passdlg.exec() == TQDialog::Accepted) { setEnabled(false); if (LDAPManager::unbondRealm(m_realms[realmName], passdlg.m_base->ldapAdminUsername->text(), passdlg.m_base->ldapAdminPassword->password(), passdlg.m_base->ldapAdminRealm->text(), &errorString) == 0) { // Success! realmcfg.bonded = false; m_realms.remove(realmName); m_realms.insert(realmName, realmcfg); save(); } else { KMessageBox::error(this, i18n("Unable to unbond from realm!

%1").arg(errorString), i18n("Unable to Unbond from Realm")); } setEnabled(true); } } } updateRealmList(); } void LDAPConfig::realmProperties() { TQListViewItem *selrealm = base->ldapRealmList->selectedItem(); if (selrealm) { RealmPropertiesDialog rpdialog(&m_realms, selrealm->text(1), this); if (rpdialog.exec() == TQDialog::Accepted) { updateRealmList(); changed(); } } } int LDAPConfig::buttons() { return TDECModule::Apply|TDECModule::Help; } TQString LDAPConfig::quickHelp() const { return i18n("This module configures which LDAP realms TDE uses for authentication."); }