Branch: master

f4141d45 2015-09-01 19:26:00 Timothy Pearson
Add ability to generate user PKI keys and certificates
M src/ldapmgr.h
M src/userconfigbase.ui
M src/userconfigdlg.cpp
M src/userconfigdlg.h
diff --git a/src/ldapmgr.h b/src/ldapmgr.h
index 48fe954..a366f6e 100644
--- a/src/ldapmgr.h
+++ b/src/ldapmgr.h
@@ -110,6 +110,8 @@
 		LDAPGroupInfoList m_groupInfoList;
 		LDAPMachineInfoList m_machineInfoList;
 		LDAPServiceInfoList m_serviceInfoList;
+
+	friend class UserConfigDialog;
 };
 
 #endif
diff --git a/src/userconfigbase.ui b/src/userconfigbase.ui
index 61e44dc..e435ecf 100644
--- a/src/userconfigbase.ui
+++ b/src/userconfigbase.ui
@@ -841,6 +841,127 @@
 						</spacer>
 					</grid>
 				</widget>
+				<widget class="TQWidget">
+					<property name="name">
+						<cstring>passwordTab</cstring>
+					</property>
+					<attribute name="title">
+						<string>Certificates and Cards</string>
+					</attribute>
+					<grid>
+						<property name="name">
+							<cstring>unnamed</cstring>
+						</property>
+						<widget class="TQLabel" row="0" column="0" colspan="1">
+							<property name="name">
+								<cstring>certificateIcon</cstring>
+							</property>
+							<property name="sizePolicy">
+								<sizepolicy>
+									<hsizetype>4</hsizetype>
+									<vsizetype>5</vsizetype>
+									<horstretch>0</horstretch>
+									<verstretch>0</verstretch>
+								</sizepolicy>
+							</property>
+						</widget>
+						<widget class="TQLabel" row="0" column="1" colspan="2">
+							<property name="name">
+								<cstring>unnamed</cstring>
+							</property>
+							<property name="text">
+								<string>New PKI Certificate</string>
+							</property>
+						</widget>
+						<widget class="TQLabel" row="1" column="0" colspan="2">
+							<property name="name">
+								<cstring>unnamed</cstring>
+							</property>
+							<property name="text">
+								<string>Expires:</string>
+							</property>
+						</widget>
+						<widget class="KDateWidget" row="1" column="2" colspan="3">
+							<property name="name">
+								<cstring>certificateExpirationDate</cstring>
+							</property>
+							<property name="enabled">
+								<cstring>true</cstring>
+							</property>
+						</widget>
+						<widget class="TQLabel" row="2" column="0" colspan="2">
+							<property name="name">
+								<cstring>unnamed</cstring>
+							</property>
+							<property name="text">
+								<string>Private key location:</string>
+							</property>
+						</widget>
+						<widget class="KURLRequester" row="2" column="2" colspan="1">
+							<property name="name">
+								<cstring>certPrivateKeyFileName</cstring>
+							</property>
+							<property name="filter">
+								<cstring>*.key</cstring>
+							</property>
+							<property name="mode">
+								<number>17</number>
+							</property>
+						</widget>
+						<widget class="TQCheckBox" row="2" column="4" colspan="1">
+							<property name="name">
+								<cstring>certGenPrivateKey</cstring>
+							</property>
+							<property name="text">
+								<string>Create new private key</string>
+							</property>
+						</widget>
+						<widget class="TQLabel" row="3" column="0" colspan="2">
+							<property name="name">
+								<cstring>unnamed</cstring>
+							</property>
+							<property name="text">
+								<string>Public certificate location:</string>
+							</property>
+						</widget>
+						<widget class="KURLRequester" row="3" column="2" colspan="3">
+							<property name="name">
+								<cstring>certPublicCertFileName</cstring>
+							</property>
+							<property name="filter">
+								<cstring>*.pem</cstring>
+							</property>
+							<property name="mode">
+								<number>17</number>
+							</property>
+						</widget>
+						<widget class="KPushButton" row="4" column="0" colspan="5">
+							<property name="name">
+								<cstring>createCertificate</cstring>
+							</property>
+							<property name="text">
+								<string>Generate New PKI Certificate</string>
+							</property>
+						</widget>
+						<spacer row="10" column="0">
+							<property name="name" stdset="0">
+								<cstring>Spacer2</cstring>
+							</property>
+							<property name="orientation">
+								<enum>Vertical</enum>
+							</property>
+							<property name="sizeType">
+								<enum>Expanding</enum>
+							</property>
+							<property name="sizeHint">
+								<size>
+									<width>20</width>
+									<height>20</height>
+								</size>
+							</property>
+						</spacer>
+					</grid>
+				</widget>
 			</widget>
 		</grid>
 	</widget>
diff --git a/src/userconfigdlg.cpp b/src/userconfigdlg.cpp
index 8f23ed5..55c5d90 100644
--- a/src/userconfigdlg.cpp
+++ b/src/userconfigdlg.cpp
@@ -22,6 +22,9 @@
 #include <klineedit.h>
 #include <ktextedit.h>
 #include <knuminput.h>
+#include <tdetempfile.h>
+#include <kstandarddirs.h>
+#include <tdemessagebox.h>
 #include <tdeactionselector.h>
 #include <tqlistbox.h>
 #include <kpushbutton.h>
@@ -32,6 +35,7 @@
 #include <kcombobox.h>
 #include <tqradiobutton.h>
 #include <tqcheckbox.h>
+#include <kdatewidget.h>
 #include <kdatetimewidget.h>
 #include <kpassdlg.h>
 #include <kiconloader.h>
@@ -60,6 +64,7 @@
 	m_base->userIcon->setPixmap(SmallIcon("personal.png"));
 	m_base->groupsIcon->setPixmap(SmallIcon("tdmconfig.png"));
 	m_base->passwordIcon->setPixmap(SmallIcon("password.png"));
+	m_base->certificateIcon->setPixmap(SmallIcon("password.png"));
 
 	connect(m_base->loginName, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(processLockouts()));
 	connect(m_base->realName, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(processLockouts()));
@@ -70,6 +75,10 @@
 	connect(m_base->requirePasswordAging, TQT_SIGNAL(clicked()), this, TQT_SLOT(processLockouts()));
 	connect(m_base->requirePasswordMinAge, TQT_SIGNAL(clicked()), this, TQT_SLOT(processLockouts()));
 	connect(m_base->primaryGroup, TQT_SIGNAL(activated(const TQString&)), this, TQT_SLOT(processLockouts()));
+	connect(m_base->certGenPrivateKey, TQT_SIGNAL(clicked()), this, TQT_SLOT(processLockouts()));
+	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()));
 
 	if (m_user.status == KRB5_DISABLED_ACCOUNT) {
 		m_base->userStatusEnabled->setChecked(false);
@@ -127,6 +136,10 @@
 	m_base->telephoneNumber->setText(m_user.telephoneNumber);
 	m_base->faxNumber->setText(m_user.faxNumber);
 	m_base->email->setText(m_user.email);
+
+	// Certificate generation information
+	TQDateTime suggestedExpiration = TQDateTime::currentDateTime().addDays(KERBEROS_PKI_KRB_EXPIRY_DAYS);
+	m_base->certificateExpirationDate->setDate(suggestedExpiration.date());
 
 	processLockouts();
 }
@@ -252,9 +265,62 @@
 	}
 	enableButton(KDialogBase::Ok, ok_enabled);
 
+	if (m_base->certPrivateKeyFileName->url() == "") {
+		ok_enabled = false;
+	}
+	if (m_base->certPublicCertFileName->url() == "") {
+		ok_enabled = false;
+	}
+	if (!m_base->certGenPrivateKey->isChecked()) {
+		if (!TQFile(m_base->certPrivateKeyFileName->url()).exists()) {
+			ok_enabled = false;
+		}
+	}
+	m_base->createCertificate->setEnabled(ok_enabled);
+
 	m_prevPrimaryGroup = m_base->primaryGroup->currentText();
 }
 
+void UserConfigDialog::createPKICertificate() {
+	TQString errorstring;
+	LDAPCertConfig certinfo;
+	LDAPRealmConfigList realms = LDAPManager::fetchAndReadTDERealmList();
+
+	certinfo.kerberosExpiryDays = 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) {
+			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;
+		}
+	}
+
+	// Get the CA root private key from LDAP
+	// WARNING
+	// Anyone with access to this key would be able to create accounts that could access any resource on the realm!
+	// Secure the key file accordingly...
+	KTempFile caPrivateKeyTempFile(locateLocal("tmp", "krbcakey"), ".key.pem", 0600);
+	caPrivateKeyTempFile.setAutoDelete(true);
+	TQFile* caPrivateKeyFile = caPrivateKeyTempFile.file();
+	if (!caPrivateKeyFile) {
+		KMessageBox::sorry(this, i18n("<qt><b>Unable to obtain root certificate for realm %1!</b><p>Details: %2</qt>").arg(realms[m_ldapconfig->m_ldapmanager->realm()].name.upper()).arg(i18n("Unable to create or open temporary file '%s'").arg(caPrivateKeyTempFile.name())), i18n("Unable to Obtain Certificate"));
+		return;
+	}
+	if (m_ldapconfig->m_ldapmanager->getTDECertificate("privateRootCertificateKey", caPrivateKeyFile, &errorstring) != 0) {
+		KMessageBox::sorry(this, i18n("<qt><b>Unable to obtain root certificate for realm %1!</b><p>Details: %2</qt>").arg(realms[m_ldapconfig->m_ldapmanager->realm()].name.upper()).arg(errorstring), i18n("Unable to Obtain Certificate"));
+		return;
+	}
+	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) {
 ** Diff limit reached (max: 250 lines) **