Branch: master

d21c8923 2015-09-03 00:03:36 Timothy Pearson
Add CRL support
M cert-updater/main.cpp
M confskel/openldap/ldif/olcDatabase.ldif
M confskel/openldap/ldif/tde-core.ldif
M src/ldapcontroller.cpp
M src/ldapcontroller.h
M src/ldapcontrollerconfigbase.ui
diff --git a/cert-updater/main.cpp b/cert-updater/main.cpp
index 0dc3a27..3466eaf 100644
--- a/cert-updater/main.cpp
+++ b/cert-updater/main.cpp
@@ -90,6 +90,8 @@
 		force_update = true;
 	}
 
+	bool ca_modified = false;
+
 	//======================================================================================================================================================
 	//
 	// Updater code follows
@@ -174,6 +176,13 @@
 					if (uploadKerberosCAFileToLDAP(ldap_mgr, &errorstring) != 0) {
 						printf("[ERROR] Unable to upload new certificate to LDAP server!\n%s\n", errorstring.ascii()); fflush(stdout);
 					}
+
+					// CRL
+					if (ldap_mgr->generatePKICRL(m_certconfig.caExpiryDays, m_realmconfig[m_defaultRealm], &errorstring) != 0) {
+						printf("[ERROR] Unable to generate CRL!\n%s\n", errorstring.ascii()); fflush(stdout);
+					}
+
+					ca_modified = true;
 		
 					delete ldap_mgr;
 				}
@@ -261,6 +270,9 @@
 		}
 	}
 
+	if (ca_modified)
+		force_update = true;
+
 	// Kerberos
 	if (TQFile::exists(kdc_certfile)) {
 		certExpiry = LDAPManager::getCertificateExpiration(kdc_certfile);
diff --git a/confskel/openldap/ldif/olcDatabase.ldif b/confskel/openldap/ldif/olcDatabase.ldif
index 12ee550..29b107d 100644
--- a/confskel/openldap/ldif/olcDatabase.ldif
+++ b/confskel/openldap/ldif/olcDatabase.ldif
@@ -4,7 +4,7 @@
 olcDatabase: {@@@LDIFSCHEMANUMBER@@@}hdb
 olcDbDirectory: /var/lib/ldap
 olcSuffix: @@@REALM_DCNAME@@@
-olcAccess: {0}to attrs=userPassword,shadowLastChange,krb5Key,krb5PrincipalName,krb5KeyVersionNumber,krb5MaxLife,krb5MaxRenew,krb5KDCFlags,privateRootCertificateKey
+olcAccess: {0}to attrs=userPassword,shadowLastChange,krb5Key,krb5PrincipalName,krb5KeyVersionNumber,krb5MaxLife,krb5MaxRenew,krb5KDCFlags,privateRootCertificateKey,pkiCertificate
   by group/groupOfNames/member.exact="cn=@@@ADMINGROUP@@@,ou=groups,ou=core,ou=realm,@@@REALM_DCNAME@@@" write
   by dn.base="uid=@@@ADMINUSER@@@,ou=users,ou=core,ou=realm,@@@REALM_DCNAME@@@"
   by sockurl.regex="^ldapi:///$" write
diff --git a/confskel/openldap/ldif/tde-core.ldif b/confskel/openldap/ldif/tde-core.ldif
index 8a72c00..d2647c6 100644
--- a/confskel/openldap/ldif/tde-core.ldif
+++ b/confskel/openldap/ldif/tde-core.ldif
@@ -26,10 +26,13 @@
 olcAttributeTypes: {18} ( 1.3.6.1.4.1.40364.1.1.19 NAME 'builtinStandardUserGroup' DESC 'Built-in standard user group distinguished name' SUP name )
 # Used for storing certificate management settings
 olcAttributeTypes: {19} ( 1.3.6.1.4.1.40364.1.1.20 NAME 'publicRootCertificateOriginServer' DESC 'Certificate authority root certificate origin server' SUP name )
+# Used for storing PKI user certificates and certificate status
+olcAttributeTypes: {20} ( 1.3.6.1.4.1.40364.1.1.21 NAME 'pkiCertificate' DESC 'User PKI certificate and status encoded with text mode TQDataStream TQPair<uint32_t, TQByteArray>' SUP name )
+olcAttributeTypes: {21} ( 1.3.6.1.4.1.40364.1.1.22 NAME 'publicRootCertificateRevocationList' DESC 'Certificate authority root certificate revocation list' SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 SINGLE-VALUE )
 olcObjectClasses: {0} ( 1.3.6.1.4.1.40364.1.2.1 NAME 'tdeExtendedUserData' SUP top AUXILIARY MAY ( website
  URL $ managerName $ secretaryName $ teletexId $ preferredDelivery $ locallyUniqueID $ notes $ pwdLastSet $ badPwdCount $ badPasswordTime $ lastLogon $ lastLogoff ) )
-olcObjectClasses: {1} ( 1.3.6.1.4.1.40364.1.2.2 NAME 'tdeAccountObject' SUP top AUXILIARY MAY tdeBuiltinAccount )
-olcObjectClasses: {2} ( 1.3.6.1.4.1.40364.1.2.3 NAME 'tdeCertificateStore' SUP top AUXILIARY MAY ( tdeBuiltinAccount $ publicRootCertificate $ privateRootCertificateKey $ publicRootCertificateOriginServer ) )
+olcObjectClasses: {1} ( 1.3.6.1.4.1.40364.1.2.2 NAME 'tdeAccountObject' SUP top AUXILIARY MAY ( tdeBuiltinAccount $ pkiCertificate ) )
+olcObjectClasses: {2} ( 1.3.6.1.4.1.40364.1.2.3 NAME 'tdeCertificateStore' SUP top AUXILIARY MAY ( tdeBuiltinAccount $ publicRootCertificate $ privateRootCertificateKey $ publicRootCertificateRevocationList $ publicRootCertificateOriginServer ) )
 olcObjectClasses: {3} ( 1.3.6.1.4.1.40364.1.2.4 NAME 'tdeBuiltinStore' SUP top AUXILIARY MAY ( tdeBuiltinAccount $ builtinRealmAdminAccount $ builtinRealmAdminGroup $ builtinMachineAdminGroup $ builtinStandardUserGroup ) )
 structuralObjectClass: olcSchemaConfig
 creatorsName: cn=config
diff --git a/src/ldapcontroller.cpp b/src/ldapcontroller.cpp
index 092fe71..ceb4c52 100644
--- a/src/ldapcontroller.cpp
+++ b/src/ldapcontroller.cpp
@@ -130,6 +130,8 @@
 	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->crlRegenerate, TQT_SIGNAL(clicked()), this, TQT_SLOT(btncrlRegenerate()));
+
 	connect(m_base->btnChangeLDAPRootPassword, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnChangeLDAPRootPassword()));
 	connect(m_base->btnChangeRealmAdminPassword, TQT_SIGNAL(clicked()), this, TQT_SLOT(btnChangeRealmAdminPassword()));
 
@@ -145,6 +147,7 @@
 	connect(m_base->multiMasterReplicationMappings, TQT_SIGNAL(executed(TQListViewItem*)), this, TQT_SLOT(modifySelectedMultiMasterReplication()));
 
 	connect(m_base->advancedCaCertExpiry, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(caCertExpiryChanged()));
+	connect(m_base->advancedCaCrlExpiry, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(caCrlCertExpiryChanged()));
 	connect(m_base->advancedKerberosCertExpiry, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(kerberosCertExpiryChanged()));
 	connect(m_base->advancedLdapCertExpiry, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(ldapCertExpiryChanged()));
 
@@ -384,6 +387,7 @@
 	// Load cert config
 	m_systemconfig->setGroup("Certificates");
 	m_certconfig.caExpiryDays = m_systemconfig->readNumEntry("caExpiryDays", KERBEROS_PKI_PEMKEY_EXPIRY_DAYS);
+	m_certconfig.caCrlExpiryDays = m_systemconfig->readNumEntry("caCrlExpiryDays", KERBEROS_PKI_CRL_EXPIRY_DAYS);
 	m_certconfig.kerberosExpiryDays = m_systemconfig->readNumEntry("kerberosExpiryDays", KERBEROS_PKI_KRB_EXPIRY_DAYS);
 	m_certconfig.ldapExpiryDays = m_systemconfig->readNumEntry("ldapExpiryDays", KERBEROS_PKI_LDAP_EXPIRY_DAYS);
 	m_certconfig.countryName = m_systemconfig->readEntry("countryName");
@@ -470,6 +474,7 @@
 		}
 
 		m_base->advancedCaCertExpiry->setValue(m_certconfig.caExpiryDays);
+		m_base->advancedCaCrlExpiry->setValue(m_certconfig.caCrlExpiryDays);
 		m_base->advancedKerberosCertExpiry->setValue(m_certconfig.kerberosExpiryDays);
 		m_base->advancedLdapCertExpiry->setValue(m_certconfig.ldapExpiryDays);
 
@@ -504,6 +509,13 @@
 	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());
+
+	TQString realmname = m_defaultRealm.upper();
+	LDAPCredentials* credentials = new LDAPCredentials;
+	credentials->username = "";
+	credentials->password = "";
+	credentials->realm = realmname;
+	LDAPManager* ldap_mgr = new LDAPManager(realmname, "ldapi://", credentials);
 
 	// Certificate Authority
 	if (TQFile::exists(KERBEROS_PKI_PEM_FILE)) {
@@ -570,6 +582,38 @@
 		m_base->ldapExpiryString->setText("File not found");
 		m_base->ldapExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_NOTFOUND);
 	}
+
+	// Certificate Revocation List
+// FIXME
+// KSSLCertificate does not appear to understand the CRL format
+// Debug and reactivate this code
+#if 0
+	TQByteArray certificateContents;
+	if (ldap_mgr->getTDECertificate("publicRootCertificateRevocationList", &certificateContents, NULL) == 0) {
+		certExpiry = LDAPManager::getCertificateExpiration(certificateContents);
+		if (certExpiry >= now) {
+			m_base->crlExpiryString->setText("Expires " + certExpiry.toString());
+			if (certExpiry >= soon) {
+				m_base->crlExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_ACTIVE);
+			}
+			else {
+				m_base->crlExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_STALE);
+			}
+		}
+		else {
+			m_base->crlExpiryString->setText("Expired " + certExpiry.toString());
+			m_base->crlExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_EXPIRED);
+		}
+	}
+	else {
+		m_base->crlExpiryString->setText("File not found");
+		m_base->crlExpiryString->setPaletteForegroundColor(CERT_STATUS_COLOR_NOTFOUND);
+	}
+#else
+	m_base->crlExpiryString->setText("Unknown");
+#endif
+
+	delete ldap_mgr;
 }
 
 void LDAPController::btncaSetMaster() {
@@ -710,6 +754,26 @@
 		TDEIO::CopyJob* job = TDEIO::copy(src, dest, true);
 		connect(job, TQT_SIGNAL(result(TDEIO::Job*)), this, TQT_SLOT(slotCertCopyResult(TDEIO::Job*)));
 	}
+}
+
+void LDAPController::btncrlRegenerate() {
+	TQString errstr;
+
+	// Bind to realm
+	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 (ldap_mgr->generatePKICRL(m_certconfig.caCrlExpiryDays, m_realmconfig[m_defaultRealm], KERBEROS_PKI_PEMKEY_FILE, KERBEROS_PKI_CRLDB_FILE, &errstr) != 0) {
+		KMessageBox::error(this, i18n("<qt><b>Unable to regenerate CRL</b><p>Details: %1</qt>").arg(errstr), i18n("Unable to Regenerate CRL"));
+	}
+
+	delete ldap_mgr;
+
+	load();
 }
 
 void LDAPController::slotCertCopyResult(TDEIO::Job* job) {
@@ -927,6 +991,12 @@
 	emit(changed());
 }
 
+void LDAPController::caCrlExpiryChanged() {
+	m_certconfig.caCrlExpiryDays = m_base->advancedCaCrlExpiry->value();
+
+	emit(changed());
+}
+
 void LDAPController::kerberosCertExpiryChanged() {
 	m_certconfig.kerberosExpiryDays = m_base->advancedKerberosCertExpiry->value();
 
@@ -954,6 +1024,7 @@
 	// Write cert config
 	m_systemconfig->setGroup("Certificates");
 	m_systemconfig->writeEntry("caExpiryDays", m_certconfig.caExpiryDays);
+	m_systemconfig->writeEntry("caCrlExpiryDays", m_certconfig.caCrlExpiryDays);
 	m_systemconfig->writeEntry("kerberosExpiryDays", m_certconfig.kerberosExpiryDays);
 	m_systemconfig->writeEntry("ldapExpiryDays", m_certconfig.ldapExpiryDays);
 	m_systemconfig->writeEntry("countryName", m_certconfig.countryName);
diff --git a/src/ldapcontroller.h b/src/ldapcontroller.h
index 84bfc7c..9beb7c0 100644
--- a/src/ldapcontroller.h
+++ b/src/ldapcontroller.h
@@ -78,6 +78,7 @@
 		void btnldapRegenerate();
 		void btnldapExportKey();
 		void btnldapExportCert();
+		void btncrlRegenerate();
 		void slotCertCopyResult(TDEIO::Job*);
 
 		void btnChangeLDAPRootPassword();
@@ -91,6 +92,7 @@
 		void modifySelectedMultiMasterReplication();
 
 		void caCertExpiryChanged();
+		void caCrlExpiryChanged();
 		void kerberosCertExpiryChanged();
 		void ldapCertExpiryChanged();
 
diff --git a/src/ldapcontrollerconfigbase.ui b/src/ldapcontrollerconfigbase.ui
index 85a4a00..8fa2cde 100644
--- a/src/ldapcontrollerconfigbase.ui
+++ b/src/ldapcontrollerconfigbase.ui
@@ -215,36 +215,20 @@
 									<cstring>unnamed</cstring>
 								</property>
 								<property name="text">
-									<cstring>Certificate Authority:</cstring>
+									<cstring>Certificate Revocation List:</cstring>
 								</property>
 							</widget>
 							<widget class="TQLabel" row="2" column="0" colspan="1">
 								<property name="name">
-									<cstring>caExpiryString</cstring>
+									<cstring>crlExpiryString</cstring>
 								</property>
 							</widget>
-							<widget class="TQPushButton" row="1" column="2" colspan="1" rowspan="2">
+							<widget class="TQPushButton" row="1" column="3" colspan="2" rowspan="2">
 								<property name="name">
-									<cstring>caRegenerate</cstring>
 ** Diff limit reached (max: 250 lines) **