From 86e14dadc9d81d186f23ce6217ac5d17c969f003 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 6 Jun 2012 17:38:14 -0500 Subject: [PATCH] Add certificte and sudo handling routines --- src/libtdeldap.cpp | 225 +++++++++++++++++++++++++++++++++++++++++++-- src/libtdeldap.h | 25 +++++ 2 files changed, 242 insertions(+), 8 deletions(-) diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp index 1f1bf7a..936bb94 100644 --- a/src/libtdeldap.cpp +++ b/src/libtdeldap.cpp @@ -47,7 +47,15 @@ // FIXME // Connect this to CMake/Automake #define KDE_CONFDIR "/etc/trinity" + +// FIXME +// This assumes Debian! #define LDAP_FILE "/etc/ldap/ldap.conf" +#define LDAP_SECONDARY_FILE "/etc/ldap.conf" +#define TDELDAP_SUDO_D_FILE "/etc/sudoers.d/tde-realm-admins" +#define CRON_UPDATE_NSS_FILE "/etc/cron.daily/upd-local-nss-db" + +#define CRON_UPDATE_NSS_COMMAND "/usr/sbin/nss_updatedb ldap" int requested_ldap_version = LDAP_VERSION3; char* ldap_user_and_operational_attributes[2] = {"*", "+"}; @@ -586,9 +594,7 @@ LDAPUserInfo LDAPManager::getUserByDistinguishedName(TQString dn) { } else { LDAPMessage* msg; - struct timeval timeout; - timeout.tv_sec = 10; // 10 second timeout - retcode = ldap_search_ext_s(m_ldap, dn.ascii(), LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, &timeout, 0, &msg); + retcode = ldap_search_ext_s(m_ldap, dn.ascii(), LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg); if (retcode != LDAP_SUCCESS) { KMessageBox::error(0, i18n("LDAP search failure

Reason: [%3] %4").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error")); return LDAPUserInfo(); @@ -618,9 +624,7 @@ LDAPGroupInfo LDAPManager::getGroupByDistinguishedName(TQString dn, TQString *er } else { LDAPMessage* msg; - struct timeval timeout; - timeout.tv_sec = 10; // 10 second timeout - retcode = ldap_search_ext_s(m_ldap, dn.ascii(), LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, &timeout, 0, &msg); + retcode = ldap_search_ext_s(m_ldap, dn.ascii(), LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg); if (retcode != LDAP_SUCCESS) { if (errstr) *errstr = i18n("LDAP search failure

Reason: [%3] %4").arg(retcode).arg(ldap_err2string(retcode)); else KMessageBox::error(0, i18n("LDAP search failure

Reason: [%3] %4").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error")); @@ -1311,7 +1315,7 @@ int LDAPManager::writeCertificateFileIntoDirectory(TQByteArray cert, TQString at mods[i] = NULL; // Perform LDAP update - retcode = ldap_modify_ext_s(m_ldap, TQString("cn=certificate store,o=tde,cn=tde realm data,ou=master services,ou=core,ou=realm,%1").arg(m_basedc).ascii(), mods, NULL, NULL); // RAJA FIXME + retcode = ldap_modify_ext_s(m_ldap, TQString("cn=certificate store,o=tde,cn=tde realm data,ou=master services,ou=core,ou=realm,%1").arg(m_basedc).ascii(), mods, NULL, NULL); // Clean up mods[i] = prevterm; @@ -1431,7 +1435,7 @@ void LDAPManager::writeLDAPConfFile(LDAPRealmConfig realmcfg) { stream << "bind_policy " << m_bindPolicy.lower() << "\n"; stream << "pam_password " << m_passwordHash.lower() << "\n"; stream << "nss_initgroups_ignoreusers " << m_ignoredUsers << "\n"; - stream << "tls_cacert /etc/trinity/ldap/tde-ca/public/argus5.starlink.edu.ldap.crt" << "\n"; + stream << "tls_cacert " << KERBEROS_PKI_PUBLICDIR << realmcfg.admin_server << ".ldap.crt" << "\n"; } file.close(); @@ -1439,9 +1443,205 @@ void LDAPManager::writeLDAPConfFile(LDAPRealmConfig realmcfg) { chmod(LDAP_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); + system(TQString("ln -s %1 %2").arg(LDAP_FILE).arg(LDAP_SECONDARY_FILE).ascii()); + delete systemconfig; } +LDAPTDEBuiltinsInfo LDAPManager::parseLDAPTDEBuiltinsRecord(LDAPMessage* entry) { + char* dn = NULL; + char* attr; + struct berval **vals; + BerElement* ber; + int i; + + LDAPTDEBuiltinsInfo builtininfo; + + if((dn = ldap_get_dn(m_ldap, entry)) != NULL) { + printf("Returned dn: %s\n", dn); + ldap_memfree(dn); + } + + for( attr = ldap_first_attribute(m_ldap, entry, &ber); attr != NULL; attr = ldap_next_attribute(m_ldap, entry, ber)) { + if ((vals = ldap_get_values_len(m_ldap, entry, attr)) != NULL) { +for(i = 0; vals[i] != NULL; i++) { + printf("[RAJA DEBUG 160.3] %s: %s\n\r", attr, vals[i]->bv_val); +} + builtininfo.informationValid = true; + TQString ldap_field = attr; + i=0; + if (ldap_field == "builtinRealmAdminAccount") { + builtininfo.builtinRealmAdminAccount = vals[i]->bv_val; + } + else if (ldap_field == "builtinRealmAdminGroup") { + builtininfo.builtinRealmAdminGroup = vals[i]->bv_val; + } + else if (ldap_field == "builtinMachineAdminGroup") { + builtininfo.builtinMachineAdminGroup = vals[i]->bv_val; + } + else if (ldap_field == "builtinStandardUserGroup") { + builtininfo.builtinStandardUserGroup = vals[i]->bv_val; + } + ldap_value_free_len(vals); + } + ldap_memfree(attr); + } + + if (ber != NULL) { + ber_free(ber, 0); + } + + printf("\n\r"); + + return builtininfo; +} + +LDAPTDEBuiltinsInfo LDAPManager::getTDEBuiltinMappings(TQString *errstr) { + int retcode; + LDAPTDEBuiltinsInfo builtininfo; + + TQString dn = TQString("cn=builtin mappings,o=tde,cn=tde realm data,ou=master services,ou=core,ou=realm,%1").arg(m_basedc); + + if (bind(errstr) < 0) { + return LDAPTDEBuiltinsInfo(); + } + else { + LDAPMessage* msg; + retcode = ldap_search_ext_s(m_ldap, dn.ascii(), LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg); + if (retcode != LDAP_SUCCESS) { + if (errstr) *errstr = i18n("LDAP search failure

Reason: [%3] %4").arg(retcode).arg(ldap_err2string(retcode)); + else KMessageBox::error(0, i18n("LDAP search failure

Reason: [%3] %4").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error")); + return LDAPTDEBuiltinsInfo(); + } + + // Iterate through the returned entries + LDAPMessage* entry; + for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) { + builtininfo = parseLDAPTDEBuiltinsRecord(entry); + } + + // clean up + ldap_msgfree(msg); + + return builtininfo; + } + + return LDAPTDEBuiltinsInfo(); +} + +int LDAPManager::getTDECertificate(TQString certificateName, TQString fileName, TQString *errstr) { + int retcode; + int returncode; + LDAPTDEBuiltinsInfo builtininfo; + + TQString dn = TQString("cn=certificate store,o=tde,cn=tde realm data,ou=master services,ou=core,ou=realm,%1").arg(m_basedc); + + if (bind(errstr) < 0) { + return -1; + } + else { + LDAPMessage* msg; + retcode = ldap_search_ext_s(m_ldap, dn.ascii(), LDAP_SCOPE_SUBTREE, NULL, ldap_user_and_operational_attributes, 0, NULL, NULL, NULL, 0, &msg); + if (retcode != LDAP_SUCCESS) { + if (errstr) *errstr = i18n("LDAP search failure

Reason: [%3] %4").arg(retcode).arg(ldap_err2string(retcode)); + else KMessageBox::error(0, i18n("LDAP search failure

Reason: [%3] %4").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error")); + return -1; + } + + returncode = -2; + + // Iterate through the returned entries + LDAPMessage* entry; + for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) { + char* attr; + struct berval **vals; + BerElement* ber; + int i; + + LDAPTDEBuiltinsInfo builtininfo; + + for( attr = ldap_first_attribute(m_ldap, entry, &ber); attr != NULL; attr = ldap_next_attribute(m_ldap, entry, ber)) { + if ((vals = ldap_get_values_len(m_ldap, entry, attr)) != NULL) { + builtininfo.informationValid = true; + TQString ldap_field = attr; + i=0; + if (ldap_field == certificateName) { + TQFile file(fileName); + if (file.open(IO_WriteOnly)) { + TQByteArray ba; + ba.duplicate(vals[i]->bv_val, vals[i]->bv_len); + file.writeBlock(ba); + returncode = 0; + } + } + ldap_value_free_len(vals); + } + ldap_memfree(attr); + } + + if (ber != NULL) { + ber_free(ber, 0); + } + } + + // clean up + ldap_msgfree(msg); + + return returncode; + } + + return -1; +} + +int LDAPManager::writeSudoersConfFile(TQString *errstr) { + LDAPTDEBuiltinsInfo tdebuiltins = getTDEBuiltinMappings(errstr); + if (!tdebuiltins.informationValid) { + if (errstr) *errstr = i18n("Unable to read builtin TDE user/group mappings"); + return -1; + } + + TQString localadmingroup = tdebuiltins.builtinMachineAdminGroup; + int eqpos = localadmingroup.find("=")+1; + int cmpos = localadmingroup.find(",", eqpos); + localadmingroup.truncate(cmpos); + localadmingroup.remove(0, eqpos); + + TQFile file(TDELDAP_SUDO_D_FILE); + if (file.open(IO_WriteOnly)) { + TQTextStream stream( &file ); + + stream << "# This file was automatically generated by TDE\n"; + stream << "# All changes will be lost!\n"; + stream << "\n"; + stream << "# Realm local machine administrators\n"; + stream << "%" << localadmingroup << " ALL=NOPASSWD: ALL" << "\n"; + + file.close(); + } + + chown(TDELDAP_SUDO_D_FILE, 0, 0); + chmod(TDELDAP_SUDO_D_FILE, S_IRUSR|S_IRGRP); + + return 0; +} + +void LDAPManager::writeCronFiles() { + TQFile file(CRON_UPDATE_NSS_FILE); + if (file.open(IO_WriteOnly)) { + TQTextStream stream( &file ); + + stream << "# This file was automatically generated by TDE\n"; + stream << "# All changes will be lost!\n"; + stream << "\n"; + stream << "#!/bin/sh" << "\n"; + stream << CRON_UPDATE_NSS_COMMAND << "\n"; + + file.close(); + } + + system(CRON_UPDATE_NSS_COMMAND); +} + void LDAPManager::writeTDERealmList(LDAPRealmConfigList realms, KSimpleConfig* config) { LDAPRealmConfigList::Iterator it; for (it = realms.begin(); it != realms.end(); ++it) { @@ -1568,4 +1768,13 @@ LDAPMachineInfo::~LDAPMachineInfo() { // } +LDAPTDEBuiltinsInfo::LDAPTDEBuiltinsInfo() { + // TQStrings are always initialized to TQString::null, so they don't need initialization here... + informationValid = false; +} + +LDAPTDEBuiltinsInfo::~LDAPTDEBuiltinsInfo() { + // +} + #include "libtdeldap.moc" \ No newline at end of file diff --git a/src/libtdeldap.h b/src/libtdeldap.h index bf0106a..b6d899e 100644 --- a/src/libtdeldap.h +++ b/src/libtdeldap.h @@ -31,6 +31,11 @@ #include +#define TDE_CERTIFICATE_DIR "/etc/trinity/ldap/tde-ca/" +#define KERBEROS_PKI_ANCHORDIR "/etc/trinity/ldap/tde-ca/anchors/" +#define KERBEROS_PKI_PRIVATEDIR "/etc/trinity/ldap/tde-ca/private/" +#define KERBEROS_PKI_PUBLICDIR "/etc/trinity/ldap/tde-ca/public/" + #define DEFAULT_IGNORED_USERS_LIST "avahi,avahi-autoipd,backup,bin,colord,daemon,games,gnats,haldaemon,hplip,irc,klog,landscape,libuuid,list,lp,mail,man,messagebus,news,ntp,polkituser,postfix,proxy,pulse,root,rtkit,saned,sshd,statd,sync,sys,syslog,timidity,usbmux,uucp,www-data" // Values from hdb.asn1 @@ -210,6 +215,20 @@ class LDAPMachineInfo LDAPKRB5Flags status; }; +class LDAPTDEBuiltinsInfo +{ + public: + LDAPTDEBuiltinsInfo(); + ~LDAPTDEBuiltinsInfo(); + + public: + bool informationValid; + TQString builtinRealmAdminAccount; + TQString builtinRealmAdminGroup; + TQString builtinMachineAdminGroup; + TQString builtinStandardUserGroup; +}; + typedef TQValueList LDAPUserInfoList; typedef TQValueList LDAPGroupInfoList; typedef TQValueList LDAPMachineInfoList; @@ -244,6 +263,11 @@ class LDAPManager : public TQObject { int moveKerberosEntries(TQString newSuffix, TQString* errstr=0); int writeCertificateFileIntoDirectory(TQByteArray cert, TQString attr, TQString* errstr=0); + LDAPTDEBuiltinsInfo getTDEBuiltinMappings(TQString *errstr=0); + int writeSudoersConfFile(TQString *errstr=0); + int getTDECertificate(TQString certificateName, TQString fileName, TQString *errstr=0); + + static void writeCronFiles(); static TQString getMachineFQDN(); static void writeLDAPConfFile(LDAPRealmConfig realmcfg); static void writeTDERealmList(LDAPRealmConfigList realms, KSimpleConfig* config); @@ -252,6 +276,7 @@ class LDAPManager : public TQObject { LDAPUserInfo parseLDAPUserRecord(LDAPMessage* entry); LDAPGroupInfo parseLDAPGroupRecord(LDAPMessage* entry); LDAPMachineInfo parseLDAPMachineRecord(LDAPMessage* entry); + LDAPTDEBuiltinsInfo parseLDAPTDEBuiltinsRecord(LDAPMessage* entry); private: TQString m_realm;