/*************************************************************************** * Copyright (C) 2012 - 2015 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 // 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"; static const TDECmdLineOptions options[] = { { "force", I18N_NOOP("Force certificate update"), 0 }, TDECmdLineLastOption // End of options. }; void chown_safe(const char * file, uid_t user, gid_t group) { if (chown(file, user, group) < 0) { printf("[ERROR] Chown call to '%s' for %d:%d failed!\n\r", file, user, group); } } int 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 main(int argc, char *argv[]) { TDEAboutData aboutData( "primaryrccertupdater", I18N_NOOP("Realm Certificate Updater"), version, description, TDEAboutData::License_GPL, "(c) 2012-2015, Timothy Pearson"); aboutData.addAuthor("Timothy Pearson",0, "kb9vqf@pearsoncomputing.net"); TDECmdLineArgs::init( argc, argv, &aboutData ); TDECmdLineArgs::addCmdLineOptions(options); TDEApplication::disableAutoDcopRegistration(); TDEApplication app(false, false); TDEStartupInfo::appStarted(); TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); bool force_update = false; if (args->isSet("force")) { force_update = true; } bool ca_modified = false; //====================================================================================================================================================== // // Updater code follows // //====================================================================================================================================================== // FIXME // This assumes Debian! TQString m_ldapUserName = "openldap"; TQString m_ldapGroupName = "openldap"; KSimpleConfig* m_systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" )); LDAPRealmConfigList m_realmconfig = LDAPManager::readTDERealmList(m_systemconfig, false); // Load cert config m_systemconfig->setGroup("Certificates"); LDAPCertConfig m_certconfig; 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"); // Load other defaults m_systemconfig->setGroup(NULL); TQString m_defaultRealm = m_systemconfig->readEntry("DefaultRealm"); TQDateTime certExpiry; TQDateTime now = TQDateTime::currentDateTime(); TQDateTime soon = now.addDays(7); // Keep in sync with src/ldapcontroller.cpp TQString kdc_certfile = KERBEROS_PKI_KDC_FILE; kdc_certfile.replace("@@@KDCSERVER@@@", m_realmconfig[m_defaultRealm].name.lower()); TQString ldap_certfile = LDAP_CERT_FILE; ldap_certfile.replace("@@@ADMINSERVER@@@", m_realmconfig[m_defaultRealm].name.lower()); // Certificate Authority TQString fqdn = LDAPManager::getMachineFQDN(); TQString defaultRealm = m_systemconfig->readEntry("DefaultRealm"); // Connect to LDAP TQString realmname = defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials); TQString errorstring; TQString basedn = ldap_mgr->basedn(); // Get certificate settings from LDAP TQString realmCAMaster = ldap_mgr->getRealmCAMaster(&errorstring); delete ldap_mgr; delete credentials; if (realmCAMaster == "") { printf("[WARNING] Unable to determine the realm CA master! CA will not be updated\n"); fflush(stdout); } else { if (realmCAMaster == fqdn) { printf("This server is the realm CA master\n"); fflush(stdout); TQString realmname = m_defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = ""; credentials->password = ""; credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials); if (TQFile::exists(KERBEROS_PKI_PEM_FILE)) { certExpiry = LDAPManager::getCertificateExpiration(KERBEROS_PKI_PEM_FILE); if (certExpiry >= now) { printf("Certificate %s expires %s\n", TQString(KERBEROS_PKI_PEM_FILE).ascii(), certExpiry.toString().ascii()); fflush(stdout); } if (force_update || (certExpiry < now) || ((certExpiry >= now) && (certExpiry < soon))) { printf("Regenerating certificate %s...\n", TQString(KERBEROS_PKI_PEM_FILE).ascii()); fflush(stdout); LDAPManager::generatePublicKerberosCACertificate(m_certconfig, m_realmconfig[m_defaultRealm]); // Upload the contents of KERBEROS_PKI_PEM_FILE to the LDAP server TQString errorstring; if (uploadKerberosCAFileToLDAP(ldap_mgr, &errorstring) != 0) { printf("[ERROR] Unable to upload new certificate to LDAP server!\n%s\n", errorstring.ascii()); fflush(stdout); } ca_modified = true; } // Set permissions chmod(KERBEROS_PKI_PEMKEY_FILE, S_IRUSR|S_IWUSR); chown_safe(KERBEROS_PKI_PEMKEY_FILE, 0, 0); chmod(KERBEROS_PKI_PEM_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown_safe(KERBEROS_PKI_PEM_FILE, 0, 0); } else { printf("[WARNING] Certificate file %s not found!\n", TQString(KERBEROS_PKI_PEM_FILE).ascii()); fflush(stdout); } // Check CRL expiry TQByteArray certificateContents; if (ldap_mgr->getTDECertificate("publicRootCertificateRevocationList", &certificateContents, NULL) == 0) { certExpiry = LDAPManager::getCertificateExpiration(certificateContents); if (certExpiry >= now) { printf("CRL expires %s\n", certExpiry.toString().ascii()); fflush(stdout); } if (force_update || (certExpiry < now) || ((certExpiry >= now) && (certExpiry < soon))) { printf("Regenerating CRL...\n"); fflush(stdout); LDAPManager::generatePublicKerberosCACertificate(m_certconfig, m_realmconfig[m_defaultRealm]); // Upload the new CRL to the LDAP server if (ldap_mgr->generatePKICRL(m_certconfig.caCrlExpiryDays, m_realmconfig[m_defaultRealm], KERBEROS_PKI_CRL_FILE, KERBEROS_PKI_PEMKEY_FILE, KERBEROS_PKI_CRLDB_FILE, &errorstring) != 0) { printf("[ERROR] Unable to generate CRL!\n%s\n", errorstring.ascii()); fflush(stdout); } ca_modified = true; } } delete ldap_mgr; } else { printf("This server is a realm CA slave\n"); fflush(stdout); // Connect to LDAP TQString realmname = defaultRealm.upper(); LDAPCredentials* credentials = new LDAPCredentials; credentials->username = "cn=admin," + basedn; m_systemconfig->setGroup("Replication"); credentials->password = m_systemconfig->readEntry("Password"); m_systemconfig->setGroup(NULL); credentials->realm = realmname; LDAPManager* ldap_mgr = new LDAPManager(realmname, TQString("ldaps://%1/").arg(realmCAMaster), credentials); TQString errorstring; if (ldap_mgr->getTDECertificate("privateRootCertificateKey", KERBEROS_PKI_PEMKEY_FILE ".tmp", &errorstring) != 0) { printf("[ERROR] Unable to get private CA certificate key from LDAP server!\n%s\n", errorstring.ascii()); fflush(stdout); } if (ldap_mgr->getTDECertificate("publicRootCertificate", KERBEROS_PKI_PEM_FILE ".tmp", &errorstring) != 0) { printf("[ERROR] Unable to get public CA certificate from LDAP server!\n%s\n", errorstring.ascii()); fflush(stdout); } delete ldap_mgr; delete credentials; TQByteArray originalPemKeyFile; TQByteArray originalPemFile; TQByteArray newPemKeyFile; TQByteArray newPemFile; TQFile* cafile; cafile = new TQFile(KERBEROS_PKI_PEMKEY_FILE); if (cafile->open(IO_ReadOnly)) { originalPemKeyFile = cafile->readAll(); } delete cafile; cafile = new TQFile(KERBEROS_PKI_PEM_FILE); if (cafile->open(IO_ReadOnly)) { originalPemFile = cafile->readAll(); } delete cafile; cafile = new TQFile(KERBEROS_PKI_PEMKEY_FILE ".tmp"); if (cafile->open(IO_ReadOnly)) { newPemKeyFile = cafile->readAll(); } delete cafile; cafile = new TQFile(KERBEROS_PKI_PEM_FILE ".tmp"); if (cafile->open(IO_ReadOnly)) { newPemFile = cafile->readAll(); } delete cafile; if ((originalPemKeyFile == newPemKeyFile) && (originalPemFile == newPemFile)) { unlink(KERBEROS_PKI_PEMKEY_FILE ".tmp"); unlink(KERBEROS_PKI_PEM_FILE ".tmp"); printf("Certificates have not changed since last update\n"); } else { unlink(KERBEROS_PKI_PEMKEY_FILE); unlink(KERBEROS_PKI_PEM_FILE); rename(KERBEROS_PKI_PEMKEY_FILE ".tmp", KERBEROS_PKI_PEMKEY_FILE); rename(KERBEROS_PKI_PEM_FILE ".tmp", KERBEROS_PKI_PEM_FILE); force_update = true; printf("Certificates have changed, forcing certificate regeneration\n"); } // Set permissions chmod(KERBEROS_PKI_PEMKEY_FILE, S_IRUSR|S_IWUSR); chown_safe(KERBEROS_PKI_PEMKEY_FILE, 0, 0); chmod(KERBEROS_PKI_PEM_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); chown_safe(KERBEROS_PKI_PEM_FILE, 0, 0); } } if (ca_modified) { force_update = true; } // Kerberos if (TQFile::exists(kdc_certfile)) { certExpiry = LDAPManager::getCertificateExpiration(kdc_certfile); if (certExpiry >= now) { printf("Certificate %s expires %s\n", kdc_certfile.ascii(), certExpiry.toString().ascii()); fflush(stdout); } if (force_update || (certExpiry < now) || ((certExpiry >= now) && (certExpiry < soon))) { printf("Regenerating certificate %s...\n", kdc_certfile.ascii()); fflush(stdout); LDAPManager::generatePublicKerberosCertificate(m_certconfig, m_realmconfig[m_defaultRealm]); } } else { printf("[WARNING] Certificate file %s not found!\n", kdc_certfile.ascii()); fflush(stdout); } // LDAP if (TQFile::exists(ldap_certfile)) { certExpiry = LDAPManager::getCertificateExpiration(ldap_certfile); if (certExpiry >= now) { printf("Certificate %s expires %s\n", ldap_certfile.ascii(), certExpiry.toString().ascii()); fflush(stdout); } if (force_update || (certExpiry < now) || ((certExpiry >= now) && (certExpiry < soon))) { printf("Regenerating certificate %s...\n", ldap_certfile.ascii()); fflush(stdout); 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); } } else { printf("[WARNING] Certificate file %s not found!\n", ldap_certfile.ascii()); fflush(stdout); } delete m_systemconfig; //====================================================================================================================================================== return 0; }