/*************************************************************************** * 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 "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 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("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->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("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(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("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(m_prevRole); } 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(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("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()) { 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("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); } 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("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"); } } 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."); }