From f6459b79852caa355c535d96b9a6709a8b85814f Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Thu, 21 Mar 2013 00:02:51 -0500 Subject: Add new certificate updater daemon Move core code to libtdeldap --- cert-updater/Makefile.am | 10 +++ cert-updater/main.cpp | 211 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 cert-updater/Makefile.am create mode 100644 cert-updater/main.cpp (limited to 'cert-updater') diff --git a/cert-updater/Makefile.am b/cert-updater/Makefile.am new file mode 100644 index 0000000..c113f3d --- /dev/null +++ b/cert-updater/Makefile.am @@ -0,0 +1,10 @@ +INCLUDES= $(all_includes) $(KDE_INCLUDES)/tde + +bin_PROGRAMS = tdeldapcertupdater + +tdeldapcertupdater_SOURCES = main.cpp + +tdeldapcertupdater_METASOURCES = AUTO +tdeldapcertupdater_LDFLAGS = $(all_libraries) $(KDE_RPATH) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_KIO) -ltdetexteditor -ltdeldap + +KDE_OPTIONS = nofinal diff --git a/cert-updater/main.cpp b/cert-updater/main.cpp new file mode 100644 index 0000000..6994626 --- /dev/null +++ b/cert-updater/main.cpp @@ -0,0 +1,211 @@ +/*************************************************************************** + * Copyright (C) 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 + +// FIXME +// Connect this to CMake/Automake +#define KDE_CONFDIR "/etc/trinity" + +static const char description[] = + I18N_NOOP("TDE utility for updating realm certificates"); + +static const char version[] = "v0.0.1"; + +bool received_sighup = false; + +void signalHandler(int signum) +{ + printf("[INFO] Got signal %d\n\r", signum); + if (signum == SIGHUP) { + received_sighup = true; + } + else if (signum == SIGTERM) { + unlink(TDE_LDAP_CERT_UPDATER_PID_FILE); + exit(0); + } + else if (signum == SIGINT) { + unlink(TDE_LDAP_CERT_UPDATER_PID_FILE); + exit(0); + } +} + +int get_certificate_from_server(TQString certificateName, LDAPRealmConfig realmcfg) +{ + int retcode = 0; + TQString errorstring; + + // Bind anonymously to LDAP + LDAPCredentials* credentials = new LDAPCredentials; + credentials->username = ""; + credentials->password = ""; + credentials->realm = realmcfg.name.upper(); + credentials->use_tls = false; + LDAPManager* ldap_mgr = new LDAPManager(realmcfg.name.upper(), TQString("ldap://%1").arg(realmcfg.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 + printf("[INFO] Updating certificate %s from LDAP\n\r", certificateName.ascii()); + if (ldap_mgr->getTDECertificate("publicRootCertificate", certificateName, &errorstring) != 0) { + printf("[ERROR] Unable to obtain root certificate for realm %s: %s", realmcfg.name.upper().ascii(), errorstring.ascii()); + retcode = 1; + } + + delete ldap_mgr; + delete credentials; + + return retcode; +} + +int main(int argc, char *argv[]) +{ + // Register signal handler for SIGHUP + signal(SIGHUP, signalHandler); + // Register signal handler for SIGINT + signal(SIGINT, signalHandler); + // Register signal handler for SIGTERM + signal(SIGTERM, signalHandler); + + TQDir pidDir(TDE_LDAP_PID_DIR); + if (!pidDir.exists()) { + mkdir(TDE_LDAP_PID_DIR, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH); + } + TQFile pidFile(TDE_LDAP_CERT_UPDATER_PID_FILE); + if (pidFile.open(IO_WriteOnly)) { + TQTextStream stream(&pidFile); + stream << getpid(); + pidFile.close(); + } + + // Seed random number generator + struct timeval time; + gettimeofday(&time,NULL); + srand((time.tv_sec * 1000) + (time.tv_usec / 1000)); + + // Initialize TDE application libraries + TDEAboutData aboutData( "tdeldapcertupdater", I18N_NOOP("Realm Certificate Updater"), + version, description, TDEAboutData::License_GPL, + "(c) 2013, Timothy Pearson"); + aboutData.addAuthor("Timothy Pearson",0, "kb9vqf@pearsoncomputing.net"); + TDECmdLineArgs::init( argc, argv, &aboutData ); + TDEApplication::disableAutoDcopRegistration(); + + TDEApplication app(false, false); + + TDEStartupInfo::appStarted(); + + //====================================================================================================================================================== + // + // Updater code follows + // + //====================================================================================================================================================== + + KSimpleConfig* systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" )); + LDAPRealmConfigList realms = LDAPManager::readTDERealmList(systemconfig, false); + TQString m_defaultRealm = systemconfig->readEntry("DefaultRealm"); + + int prevSecondsToExpiry = (7*24*60*60); + + while (1) { + bool allDownloadsOK = true; + TQDateTime now = TQDateTime::currentDateTime(); + TQDateTime earliestCertExpiry = now.addDays(14); // Recheck every 7 days regardless of last expiry check results + + LDAPRealmConfigList::Iterator it; + for (it = realms.begin(); it != realms.end(); ++it) { + LDAPRealmConfig realmcfg = it.data(); + TQString certificateName = KERBEROS_PKI_PUBLICDIR + realmcfg.admin_server + ".ldap.crt"; + + TQDateTime certExpiry; + TQDateTime soon = now.addDays(7); // Keep in sync with src/ldapcontroller.cpp + + if (TQFile::exists(certificateName)) { + certExpiry = LDAPManager::getCertificateExpiration(certificateName); + if (certExpiry >= now) { + printf("[INFO] Certificate %s expires %s\n\r", certificateName.ascii(), certExpiry.toString().ascii()); fflush(stdout); + } + if ((certExpiry < now) || ((certExpiry >= now) && (certExpiry < soon))) { + if (get_certificate_from_server(certificateName, realmcfg) != 0) { + allDownloadsOK = false; + } + } + if (certExpiry < earliestCertExpiry) { + earliestCertExpiry = certExpiry; + } + } + else { + 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 (get_certificate_from_server(certificateName, realmcfg) != 0) { + allDownloadsOK = false; + } + } + } + + earliestCertExpiry = earliestCertExpiry.addDays(-7); // Keep in sync with now.addDays above (use negative of value given above) + int secondsToExpiry = now.secsTo(earliestCertExpiry); + secondsToExpiry = secondsToExpiry + (rand()%(5*60)); // Nothing worse than thousands of clients hammering the LDAP server all at once... + if (secondsToExpiry < 1) { + secondsToExpiry = 1; + } + if ((prevSecondsToExpiry == 1) && (allDownloadsOK)) { + // The server has not yet updated its certificate, even though our copy is close to expiration + // Therefore, do not hammer the server with useless requests! + prevSecondsToExpiry = (15*60) + (rand()%(5*60)); + } + prevSecondsToExpiry = secondsToExpiry; + printf("[INFO] Will recheck certificates in %d seconds (%d days)\n\r", secondsToExpiry, secondsToExpiry/60/60/24); fflush(stdout); + if (sleep(secondsToExpiry) != 0) { + // Signal caught + if (!received_sighup) { + break; + } + } + } + + unlink(TDE_LDAP_CERT_UPDATER_PID_FILE); + + //====================================================================================================================================================== + + return 0; +} -- cgit v1.2.1