Branch: master

7833ad28 2015-09-03 16:31:44 Timothy Pearson
Add PKI certificate controls
M src/userconfigbase.ui
M src/userconfigdlg.cpp
M src/userconfigdlg.h
diff --git a/src/userconfigbase.ui b/src/userconfigbase.ui
index e435ecf..4439222 100644
--- a/src/userconfigbase.ui
+++ b/src/userconfigbase.ui
@@ -878,7 +878,7 @@
 								<cstring>unnamed</cstring>
 							</property>
 							<property name="text">
-								<string>Expires:</string>
+								<string>Expiry:</string>
 							</property>
 						</widget>
 						<widget class="KDateWidget" row="1" column="2" colspan="3">
@@ -943,6 +943,84 @@
 								<string>Generate New PKI Certificate</string>
 							</property>
 						</widget>
+						<widget class="TQLayoutWidget" row="5" column="0" colspan="5">
+							<property name="name">
+								<cstring>unnamed_layoutwidget1</cstring>
+							</property>
+							<grid>
+								<property name="margin">
+									<number>0</number>
+								</property>
+								<widget class="TDEListView" row="5" column="0" colspan="2">
+									<column>
+										<property name="text">
+											<string>Serial</string>
+										</property>
+										<property name="clickable">
+											<bool>true</bool>
+										</property>
+										<property name="resizeable">
+											<bool>true</bool>
+										</property>
+									</column>
+									<column>
+										<property name="text">
+											<string>Status</string>
+										</property>
+										<property name="clickable">
+											<bool>true</bool>
+										</property>
+										<property name="resizeable">
+											<bool>true</bool>
+										</property>
+									</column>
+									<column>
+										<property name="text">
+											<string>Created</string>
+										</property>
+										<property name="clickable">
+											<bool>true</bool>
+										</property>
+										<property name="resizeable">
+											<bool>true</bool>
+										</property>
+									</column>
+									<column>
+										<property name="text">
+											<string>Expiry</string>
+										</property>
+										<property name="clickable">
+											<bool>true</bool>
+										</property>
+										<property name="resizeable">
+											<bool>true</bool>
+										</property>
+									</column>
+									<property name="name">
+										<cstring>certPKIDatabaseList</cstring>
+									</property>
+									<property name="rootIsDecorated">
+										<bool>false</bool>
+									</property>
+								</widget>
+								<widget class="KPushButton" row="6" column="0" colspan="1">
+									<property name="name">
+										<cstring>revokeCertificate</cstring>
+									</property>
+									<property name="text">
+										<string>Revoke Selected Certificate</string>
+									</property>
+								</widget>
+								<widget class="KPushButton" row="6" column="1" colspan="1">
+									<property name="name">
+										<cstring>downloadCertificate</cstring>
+									</property>
+									<property name="text">
+										<string>Download Selected Certificate</string>
+									</property>
+								</widget>
+							</grid>
+						</widget>
 						<spacer row="10" column="0">
 							<property name="name" stdset="0">
 								<cstring>Spacer2</cstring>
diff --git a/src/userconfigdlg.cpp b/src/userconfigdlg.cpp
index 55c5d90..d969c80 100644
--- a/src/userconfigdlg.cpp
+++ b/src/userconfigdlg.cpp
@@ -22,9 +22,11 @@
 #include <klineedit.h>
 #include <ktextedit.h>
 #include <knuminput.h>
+#include <ktempdir.h>
 #include <tdetempfile.h>
 #include <kstandarddirs.h>
 #include <tdemessagebox.h>
+#include <tdefiledialog.h>
 #include <tdeactionselector.h>
 #include <tqlistbox.h>
 #include <kpushbutton.h>
@@ -39,6 +41,7 @@
 #include <kdatetimewidget.h>
 #include <kpassdlg.h>
 #include <kiconloader.h>
+#include <ksslcertificate.h>
 
 #include "ldapmgr.h"
 #include "userconfigdlg.h"
@@ -79,6 +82,10 @@
 	connect(m_base->certPrivateKeyFileName, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(processLockouts()));
 	connect(m_base->certPublicCertFileName, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(processLockouts()));
 	connect(m_base->createCertificate, TQT_SIGNAL(clicked()), this, TQT_SLOT(createPKICertificate()));
+	connect(m_base->revokeCertificate, TQT_SIGNAL(clicked()), this, TQT_SLOT(revokePKICertificate()));
+	connect(m_base->downloadCertificate, TQT_SIGNAL(clicked()), this, TQT_SLOT(downloadPKICertificate()));
+	connect(m_base->certPKIDatabaseList, TQT_SIGNAL(selectionChanged()), this, TQT_SLOT(processLockouts()));
+	connect(m_base->certPKIDatabaseList, TQT_SIGNAL(executed(TQListViewItem*)), this, TQT_SLOT(downloadPKICertificate()));
 
 	if (m_user.status == KRB5_DISABLED_ACCOUNT) {
 		m_base->userStatusEnabled->setChecked(false);
@@ -140,6 +147,10 @@
 	// Certificate generation information
 	TQDateTime suggestedExpiration = TQDateTime::currentDateTime().addDays(KERBEROS_PKI_KRB_EXPIRY_DAYS);
 	m_base->certificateExpirationDate->setDate(suggestedExpiration.date());
+
+	m_base->certPKIDatabaseList->setAllColumnsShowFocus(true);
+	m_base->certPKIDatabaseList->setFullWidth(true);
+	updatePKICertificateList();
 
 	processLockouts();
 }
@@ -278,19 +289,35 @@
 	}
 	m_base->createCertificate->setEnabled(ok_enabled);
 
+	TQListViewItem* lvi = m_base->certPKIDatabaseList->selectedItem();
+	if (lvi) {
+		if (lvi->text(1) != i18n("Revoked")) {
+			m_base->revokeCertificate->setEnabled(true);
+			m_base->downloadCertificate->setEnabled(true);
+		}
+		else {
+			m_base->revokeCertificate->setEnabled(false);
+			m_base->downloadCertificate->setEnabled(true);
+		}
+	}
+	else {
+		m_base->revokeCertificate->setEnabled(false);
+		m_base->downloadCertificate->setEnabled(false);
+	}
+
 	m_prevPrimaryGroup = m_base->primaryGroup->currentText();
 }
 
 void UserConfigDialog::createPKICertificate() {
+	int ret;
 	TQString errorstring;
-	LDAPCertConfig certinfo;
 	LDAPRealmConfigList realms = LDAPManager::fetchAndReadTDERealmList();
 
-	certinfo.kerberosExpiryDays = TQDate::currentDate().daysTo(m_base->certificateExpirationDate->date());
+	int expirydays = TQDate::currentDate().daysTo(m_base->certificateExpirationDate->date());
 
 	if (m_base->certGenPrivateKey->isChecked()) {
 		// Generate new private key
-		if (LDAPManager::generateClientCertificatePrivateKey(m_user, realms[m_ldapconfig->m_ldapmanager->realm()], m_base->certPrivateKeyFileName->url(), &errorstring) != 0) {
+		if (LDAPManager::generateClientCertificatePrivateKey(m_base->certPrivateKeyFileName->url(), &errorstring) != 0) {
 			KMessageBox::sorry(this, i18n("<qt><b>Unable to generate new private key</b><p>Details: %1</qt>").arg(errorstring), i18n("Unable to Obtain Certificate"));
 			return;
 		}
@@ -313,12 +340,194 @@
 	}
 	caPrivateKeyTempFile.sync();
 
-	if (LDAPManager::generateClientCertificatePublicCertificate(certinfo, m_user, realms[m_ldapconfig->m_ldapmanager->realm()], caPrivateKeyTempFile.name(), m_base->certPrivateKeyFileName->url(), m_base->certPublicCertFileName->url()) != 0) {
-		KMessageBox::sorry(this, i18n("<qt><b>Unable to generate or sign certificate</b><p>Details: %1</qt>").arg(errorstring), i18n("Unable to Create Certificate"));
-	}
+	ret = LDAPManager::generateClientCertificatePublicCertificate(expirydays, m_user, realms[m_ldapconfig->m_ldapmanager->realm()], caPrivateKeyTempFile.name(), m_base->certPrivateKeyFileName->url(), m_base->certPublicCertFileName->url());
 
 	// Delete the private key as soon as possible after certificate signing
 	caPrivateKeyTempFile.unlink();
+
+	if (ret != 0) {
+		KMessageBox::sorry(this, i18n("<qt><b>Unable to generate or sign certificate</b><p>Details: %1</qt>").arg(errorstring), i18n("Unable to Create Certificate"));
+	}
+
+	// Upload new certificate to LDAP server
+	PKICertificateEntry certEntry;
+	certEntry.first = PKICertificateStatus::Valid;
+	TQFile certfile(m_base->certPublicCertFileName->url());
+	if (certfile.open(IO_ReadOnly)) {
+		certEntry.second = certfile.readAll();
+		m_user.pkiCertificates.append(certEntry);
+		if (m_ldapconfig->m_ldapmanager->writePKICertificateFilesIntoDirectory(m_user, "pkiCertificate", &errorstring) != 0) {
+			m_user.pkiCertificates.remove(certEntry);
+			KMessageBox::sorry(this, i18n("<qt><b>Unable to upload certificate to server</b><p>Details: %1</qt>").arg(errorstring), i18n("Unable to Upload Certificate"));
+		}
+	}
+	else {
+		KMessageBox::sorry(this, i18n("<qt><b>Unable to upload certificate to server</b><p>Details: %1</qt>").arg(i18n("Unable to open certificate file")), i18n("Unable to Upload Certificate"));
+	}
+
+	updatePKICertificateList();
+}
+
+void UserConfigDialog::downloadPKICertificate() {
+	TQString errorstring;
+	PKICertificateEntryList originalCertList = m_user.pkiCertificates;
+
+	TQListViewItem* lvi = m_base->certPKIDatabaseList->selectedItem();
+	if (lvi) {
+		TQString fileName = KFileDialog::getSaveFileName(TQString::null, "*.pem", 0, i18n("Save Certificate"));
+		if (fileName != "") {
+			// Find the certificate
+			PKICertificateEntryList::Iterator it;
+			for (it = m_user.pkiCertificates.begin(); it != m_user.pkiCertificates.end(); ++it) {
+				PKICertificateEntry certificateData = *it;
+
+				TQCString ssldata(certificateData.second);
+				ssldata[certificateData.second.size()] = 0;
+				ssldata.replace("-----BEGIN CERTIFICATE-----", "");
+				ssldata.replace("-----END CERTIFICATE-----", "");
+				ssldata.replace("\n", "");
+				KSSLCertificate* cert = KSSLCertificate::fromString(ssldata);
+				if (cert) {
+					if ((cert->getSerialNumber() == lvi->text(0))
+						&& (cert->getQDTNotBefore().toString() == lvi->text(2))
+						&& (cert->getQDTNotAfter().toString() == lvi->text(3))) {
+						TQFile certfile(fileName);
+						if (certfile.open(IO_WriteOnly)) {
+							certfile.writeBlock(certificateData.second);
+						}
+						else {
+							KMessageBox::sorry(this, i18n("<qt><b>Unable to download certificate</b><p>Details: %1</qt>").arg(i18n("Could not open file '%s' for writing").arg(fileName)), i18n("Unable to Download Certificate"));
+						}
+						break;
+					}
 ** Diff limit reached (max: 250 lines) **