Branch: master

521c4ed5 2015-09-03 15:07:21 Timothy Pearson
Add additional CRL manipulation methods
M src/libtdeldap.cpp
M src/libtdeldap.h
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index 950d653..156c372 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -77,6 +77,11 @@
 
 // FIXME
 // This assumes Debian!
+#define SYSTEM_CA_STORE_CERT_LOCATION "/usr/local/share/ca-certificates/"
+#define SYSTEM_CA_STORE_REGENERATE_COMMAND "update-ca-certificates"
+
+// FIXME
+// This assumes Debian!
 #define CRON_UPDATE_PRIMARY_REALM_CERTIFICATES_OPENLDAP_RELOAD_COMMAND "/etc/init.d/slapd force-reload"
 
 int requested_ldap_version = LDAP_VERSION3;
@@ -3887,6 +3892,63 @@
 	return 0;
 }
 
+int LDAPManager::installCACertificateInHostCAStore(TQString *errstr) {
+	TQString command;
+
+	if (!TQDir(SYSTEM_CA_STORE_CERT_LOCATION "ldap-trinity").exists()) {
+		command = TQString("ln -s %1 %2").arg(KERBEROS_PKI_PUBLICDIR).arg(SYSTEM_CA_STORE_CERT_LOCATION "ldap-trinity");
+		if (system(command) < 0) {
+			if (errstr) *errstr = TQString("Execution of \"%s\" failed").arg(command);
+			return -1;
+		}
+
+		if (system(SYSTEM_CA_STORE_REGENERATE_COMMAND) < 0) {
+			if (errstr) *errstr = TQString("Execution of \"%s\" failed").arg(SYSTEM_CA_STORE_REGENERATE_COMMAND);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int LDAPManager::retrieveAndInstallCaCrl(LDAPManager* manager, TQString *errstr) {
+	int retcode = 0;
+	LDAPManager* ldap_mgr = manager;
+	KSimpleConfig* systemconfig = new KSimpleConfig( TQString::fromLatin1( KDE_CONFDIR "/ldap/ldapconfigrc" ));
+	LDAPRealmConfigList realms = LDAPManager::readTDERealmList(systemconfig, false);
+
+	if (!ldap_mgr) {
+		// Get default settings
+		TQString defaultRealm = systemconfig->readEntry("DefaultRealm");
+		if (defaultRealm == "") {
+			delete systemconfig;
+			return 0;
+		}
+
+		// Bind anonymously to LDAP
+		LDAPCredentials* credentials = new LDAPCredentials;
+		credentials->username = "";
+		credentials->password = "";
+		credentials->realm = defaultRealm.upper();
+		credentials->use_tls = true;
+		ldap_mgr = new LDAPManager(defaultRealm.upper(), TQString("ldaps://%1").arg(realms[defaultRealm].admin_server).ascii(), credentials);
+	}
+
+	// Get and install the CA root CRL 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("publicRootCertificateRevocationList", KERBEROS_PKI_PUBLICDIR + realms[ldap_mgr->realm()].admin_server + ".ldap.crl", errstr) != 0) {
+		retcode = -1;
+	}
+
+	if (!manager) {
+		delete ldap_mgr;
+	}
+	delete systemconfig;
+
+	return retcode;
+}
+
 LDAPRealmConfigList LDAPManager::readTDERealmList(KSimpleConfig* config, bool disableAllBonds) {
 	LDAPRealmConfigList realms;
 
@@ -3917,7 +3979,6 @@
 				realmcfg.pkinit_require_krbtgt_otherName = config->readBoolEntry("pkinit_require_krbtgt_otherName");
 				realmcfg.win2k_pkinit = config->readBoolEntry("win2k_pkinit");
 				realmcfg.win2k_pkinit_require_binding = config->readBoolEntry("win2k_pkinit_require_binding");
-				realmcfg.certificate_revocation_list_url = config->readBoolEntry("certificate_revocation_list_url");
 				// Add realm to list
 				realms.insert(realmName, realmcfg);
 			}
@@ -3949,7 +4010,6 @@
 		config->writeEntry("pkinit_require_krbtgt_otherName", realmcfg.pkinit_require_krbtgt_otherName);
 		config->writeEntry("win2k_pkinit", realmcfg.win2k_pkinit);
 		config->writeEntry("win2k_pkinit_require_binding", realmcfg.win2k_pkinit_require_binding);
-		config->writeEntry("certificate_revocation_list_url", realmcfg.certificate_revocation_list_url);
 	}
 
 	// Delete any realms that do not exist in the realms database
@@ -3971,17 +4031,27 @@
 TQDateTime LDAPManager::getCertificateExpiration(TQByteArray certfileContents) {
 	TQDateTime ret;
 
+	KSSLCertificate* cert = NULL;
 	TQCString ssldata(certfileContents);
 	ssldata[certfileContents.size()] = 0;
-	ssldata.replace("-----BEGIN CERTIFICATE-----", "");
-	ssldata.replace("-----END CERTIFICATE-----", "");
-	ssldata.replace("-----BEGIN X509 CRL-----", "");
-	ssldata.replace("-----END X509 CRL-----", "");
 	ssldata.replace("\n", "");
-	KSSLCertificate* cert = KSSLCertificate::fromString(ssldata);
-	if (cert) {
-		ret = cert->getQDTNotAfter();
-		delete cert;
+	if (ssldata.contains("-----BEGIN CERTIFICATE-----")) {
+		ssldata.replace("-----BEGIN CERTIFICATE-----", "");
+		ssldata.replace("-----END CERTIFICATE-----", "");
+		cert = KSSLCertificate::fromString(ssldata);
+		if (cert) {
+			ret = cert->getQDTNotAfter();
+			delete cert;
+		}
+	}
+	else if (ssldata.contains("-----BEGIN X509 CRL-----")) {
+		ssldata.replace("-----BEGIN X509 CRL-----", "");
+		ssldata.replace("-----END X509 CRL-----", "");
+		cert = KSSLCertificate::crlFromString(ssldata);
+		if (cert) {
+			ret = cert->getQDTNextUpdate();
+			delete cert;
+		}
 	}
 
 	return ret;
@@ -4133,7 +4203,7 @@
 int LDAPManager::generateClientCertificatePair(int expirydays, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr) {
 	int ret;
 
-	ret = generateClientCertificatePrivateKey(user, realmcfg, privateKeyFile, errstr);
+	ret = generateClientCertificatePrivateKey(privateKeyFile, errstr);
 	if (ret == 0) {
 		ret = generateClientCertificatePublicCertificate(expirydays, user, realmcfg, signingPrivateKeyFile, privateKeyFile, publicCertFile, errstr);
 	}
@@ -4141,7 +4211,7 @@
 	return ret;
 }
 
-int LDAPManager::generateClientCertificatePrivateKey(LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString privateKeyFile, TQString *errstr) {
+int LDAPManager::generateClientCertificatePrivateKey(TQString privateKeyFile, TQString *errstr) {
 	TQString command;
 	TQString subject;
 
@@ -4149,10 +4219,6 @@
 	TQString client_reqfile = privateKeyFile + ".req";
 	TQString client_cfgfile = privateKeyFile + ".cfg";
 	unsigned int client_key_bit_length = 2048;
-
-	if (writeOpenSSLConfigurationFile(realmcfg, user, client_cfgfile, TQString::null, TQString::null, TQString::null, errstr) != 0) {
-		return -1;
-	}
 
 	// Create private key
 	command = TQString("openssl genrsa -out %1 %2").arg(client_keyfile).arg(client_key_bit_length);
@@ -4213,7 +4279,7 @@
 		if (errstr) *errstr = TQString("Execution of \"%s\" failed").arg(command);
 		return -1;
 	}
-	command = TQString("openssl x509 -req -days %1 -in %2 -CAkey %3 -CA %4 -out %5 -extfile %6 -extensions pkinit_client_cert -CAcreateserial").arg(expirydays).arg(client_reqfile).arg(signingPrivateKeyFile).arg(signing_public_certfile).arg(client_certfile).arg(OPENSSL_EXTENSIONS_FILE);
+	command = TQString("openssl x509 -req -days %1 -in %2 -CAkey %3 -CA %4 -out %5 -extfile %6 -extensions pkinit_client_cert -CAcreateserial").arg(expirydays).arg(client_reqfile).arg(signingPrivateKeyFile).arg(signing_public_certfile).arg(client_certfile).arg(client_cfgfile);
 	if (system(command) < 0) {
 		if (errstr) *errstr = TQString("Execution of \"%s\" failed").arg(command);
 		return -1;
@@ -4246,15 +4312,15 @@
 	return 0;
 }
 
-int LDAPManager::generatePKICRL(int expirydays, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString revocationDatabaseFile, TQString *errstr) {
+int LDAPManager::generatePKICRL(int expirydays, LDAPRealmConfig realmcfg, TQString crlFile, TQString signingPrivateKeyFile, TQString revocationDatabaseFile, TQString *errstr) {
 	int retcode;
 	TQString command;
 
 	LDAPUserInfoList userList = this->users(&retcode, errstr);
 	if (retcode == 0) {
 		// Generate base CRL
-		TQString crl_certfile = KERBEROS_PKI_CRL_FILE ".new";
-		TQString revoked_certfile = KERBEROS_PKI_CRL_FILE ".rev";
+		TQString crl_certfile = crlFile;
+		TQString revoked_certfile = crlFile + ".rev";
 
 		// The public certificate location varies based on the machine role
 		// Prefer the bonded realm's certificate if available
@@ -4348,6 +4414,12 @@
 		if (fileExists(revoked_certfile.ascii())) {
 			if (unlink(revoked_certfile.ascii()) < 0) {
 				if (errstr) *errstr = TQString("Unable to unlink \"%1\"").arg(revoked_certfile);
+				return -1;
+			}
+		}
+		if (fileExists(revocationDatabaseFile.ascii())) {
+			if (unlink(revocationDatabaseFile.ascii()) < 0) {
+				if (errstr) *errstr = TQString("Unable to unlink \"%1\"").arg(revocationDatabaseFile);
 				return -1;
 			}
 		}
@@ -4619,11 +4691,10 @@
 }
 
 int LDAPManager::writeOpenSSLConfigurationFile(LDAPRealmConfig realmcfg, LDAPUserInfo user, TQString opensslConfigFile, TQString caRootKeyFile, TQString caRootCertFile, TQString caRootDatabaseFile, TQString *errstr) {
-	TQString crl_url = realmcfg.certificate_revocation_list_url;
-	if (crl_url == "") {
-		// Use a default to preserve certificate validity
-		// crl_url = TQString("http://%1/%2.crl").arg(realmcfg.name).arg(realmcfg.kdc);
-	}
+	TQString ca_public_crl_certfile = KERBEROS_PKI_PUBLICDIR + realmcfg.admin_server + ".ldap.crl";
+	TQString crl_url;
+	
+	crl_url = TQString("URI:file://%1,URI:file://%2").arg(KERBEROS_PKI_CRL_FILE).arg(ca_public_crl_certfile);
 
 	if (caRootKeyFile == "") {
 		caRootKeyFile = KERBEROS_PKI_PEMKEY_FILE;
@@ -4760,19 +4831,19 @@
 		stream << "[usr_cert]" << "\n";
 		stream << "basicConstraints = CA:FALSE" << "\n";
 		stream << "keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment" << "\n";
-		stream << TQString("crlDistributionPoints = URI:%1").arg(crl_url) << "\n";
+		stream << TQString("crlDistributionPoints = %1").arg(crl_url) << "\n";
 		stream << "subjectKeyIdentifier = hash" << "\n";
 		stream << "\n";
 		stream << "[usr_cert_ke]" << "\n";
 		stream << "basicConstraints = CA:FALSE" << "\n";
 		stream << "keyUsage = critical, nonRepudiation, keyEncipherment" << "\n";
-		stream << TQString("crlDistributionPoints = URI:%1").arg(crl_url) << "\n";
+		stream << TQString("crlDistributionPoints = %1").arg(crl_url) << "\n";
 		stream << "subjectKeyIdentifier = hash" << "\n";
 		stream << "\n";
 		stream << "[proxy_cert]" << "\n";
 		stream << "basicConstraints = CA:FALSE" << "\n";
 		stream << "keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment" << "\n";
-		stream << TQString("crlDistributionPoints = URI:%1").arg(crl_url) << "\n";
+		stream << TQString("crlDistributionPoints = %1").arg(crl_url) << "\n";
 		stream << "subjectKeyIdentifier = hash" << "\n";
 		// stream << "proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:0,policy:text:foo" << "\n";
 		stream << "\n";
@@ -4792,7 +4863,7 @@
 		stream << "[pkinit_client_cert]" << "\n";
 		stream << "basicConstraints = CA:FALSE" << "\n";
 		stream << "keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment" << "\n";
-		stream << TQString("crlDistributionPoints = URI:%1").arg(crl_url) << "\n";
+		stream << TQString("crlDistributionPoints = %1").arg(crl_url) << "\n";
 		stream << "subjectKeyIdentifier = hash" << "\n";
 		stream << "authorityKeyIdentifier = keyid,issuer" << "\n";
 		stream << "issuerAltName=issuer:copy" << "\n";
 ** Diff limit reached (max: 250 lines) **