Branch: master

a97c0c3d 2015-09-02 17:28:10 Timothy Pearson
Implement several methods required for PKI certificate management
M src/libtdeldap.cpp
M src/libtdeldap.h
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index dbb4b3f..6e965fb 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -623,6 +623,22 @@
 			else if (ldap_field == "notes") {
 				userinfo.notes = vals[i]->bv_val;
 			}
+			else if (ldap_field == "pkiCertificate") {
+				int cert_count = ldap_count_values_len(vals);
+				for (i=0; i<cert_count; i++) {
+					PKICertificateEntry entry;
+
+					// Deserialize data
+					TQByteArray ba;
+					ba.duplicate(vals[i]->bv_val, vals[i]->bv_len);
+					TQDataStream stream(ba, IO_ReadOnly);
+					stream.setPrintableData(true);
+					stream >> entry;
+
+					// Append entry to list
+					userinfo.pkiCertificates.append(entry);
+				}
+			}
 			ldap_value_free_len(vals);
 		}
 		ldap_memfree(attr);
@@ -885,6 +901,24 @@
 	mods[*i]->mod_op = LDAP_MOD_REPLACE;
 	mods[*i]->mod_type = strdup(attr.ascii());
 	mods[*i]->mod_values = values;
+	(*i)++;
+}
+
+void add_multiple_binary_attributes_operation(LDAPMod **mods, int *i, TQString attr, TQByteArrayList byteArrays) {
+	int j=0;
+	struct berval **values = (berval**)malloc((byteArrays.count()+1)*sizeof(berval*));
+	for ( TQByteArrayList::Iterator it = byteArrays.begin(); it != byteArrays.end(); ++it ) {
+		if ((*it).size() > 0) {
+			values[j] = new berval;
+			values[j]->bv_len = (*it).size();
+			values[j]->bv_val = (*it).data();
+			j++;
+		}
+	}
+	values[j] = NULL;
+	mods[*i]->mod_op = LDAP_MOD_REPLACE|LDAP_MOD_BVALUES;
+	mods[*i]->mod_type = strdup(attr.ascii());
+	mods[*i]->mod_bvalues = values;
 	(*i)++;
 }
 
@@ -2678,6 +2712,65 @@
 	}
 }
 
+int LDAPManager::writePKICertificateFilesIntoDirectory(LDAPUserInfo user, TQString attr, TQString* errstr) {
+	int retcode;
+	int i;
+
+	if (bind() < 0) {
+		return -1;
+	}
+	else {
+		// Assemble the LDAPMod structure
+		// We will replace any existing attributes with the new values
+		int number_of_parameters = 1;				// 1 primary attribute
+		LDAPMod *mods[number_of_parameters+1];
+		set_up_attribute_operations(mods, number_of_parameters);
+
+		// Assemble list of serialized data structures
+		TQStringList serializedCertificateList;
+		PKICertificateEntryList::Iterator it;
+		for (it = user.pkiCertificates.begin(); it != user.pkiCertificates.end(); ++it) {
+			PKICertificateEntry certificateData = *it;
+
+			// Serialize data
+			TQByteArray ba;
+			{
+				TQDataStream stream(ba, IO_WriteOnly);
+				stream.setPrintableData(true);
+				stream << certificateData;
+			}
+			ba.resize(ba.size()+1);
+			ba[ba.size()-1] = 0;
+			serializedCertificateList.append(TQString(ba));
+		}
+
+		// Load LDAP modification requests from provided data structure
+		i=0;
+		add_multiple_attributes_operation(mods, &i, attr, serializedCertificateList);
+		LDAPMod *prevterm = mods[i];
+		mods[i] = NULL;
+
+		// Perform LDAP update
+		retcode = ldap_modify_ext_s(m_ldap, user.distinguishedName.ascii(), mods, NULL, NULL);
+
+		// Clean up
+		clean_up_attribute_operations(i, mods, prevterm, number_of_parameters);
+
+		if (retcode != LDAP_SUCCESS) {
+			if (errstr) {
+				*errstr = i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode));
+			}
+			else {
+				KMessageBox::error(0, i18n("<qt>LDAP modification failure<p>Reason: [%3] %4</qt>").arg(retcode).arg(ldap_err2string(retcode)), i18n("LDAP Error"));
+			}
+			return -2;
+		}
+		else {
+			return 0;
+		}
+	}
+}
+
 TQString LDAPManager::getRealmCAMaster(TQString* errstr) {
 	int retcode;
 	TQString realmCAMaster;
@@ -3832,6 +3925,7 @@
 		file.close();
 
 		TQCString ssldata(ba);
+		ssldata[ba.size()] = 0;
 		ssldata.replace("-----BEGIN CERTIFICATE-----", "");
 		ssldata.replace("-----END CERTIFICATE-----", "");
 		ssldata.replace("\n", "");
@@ -3974,12 +4068,12 @@
 	return 0;
 }
 
-int LDAPManager::generateClientCertificatePair(LDAPCertConfig certinfo, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr) {
+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);
 	if (ret == 0) {
-		ret = generateClientCertificatePublicCertificate(certinfo, user, realmcfg, signingPrivateKeyFile, privateKeyFile, publicCertFile, errstr);
+		ret = generateClientCertificatePublicCertificate(expirydays, user, realmcfg, signingPrivateKeyFile, privateKeyFile, publicCertFile, errstr);
 	}
 
 	return ret;
@@ -4026,7 +4120,7 @@
 	return 0;
 }
 
-int LDAPManager::generateClientCertificatePublicCertificate(LDAPCertConfig certinfo, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr) {
+int LDAPManager::generateClientCertificatePublicCertificate(int expirydays, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr) {
 	TQString command;
 	TQString subject;
 
@@ -4051,13 +4145,13 @@
 		common_name = TQString("/uid=%1").arg(user.name);
 	}
 
-	subject = TQString("\"/C=%1/ST=%2/L=%3/O=%4/OU=%5%6%7\"").arg(certinfo.countryName).arg(certinfo.stateOrProvinceName).arg(certinfo.localityName).arg(certinfo.organizationName).arg(certinfo.orgUnitName).arg(openssldcForRealm(realmcfg.name)).arg(common_name);
-	command = TQString("openssl req -days %1 -new -out %2 -key %3 -config %4 -subj %5").arg(certinfo.kerberosExpiryDays).arg(client_reqfile).arg(client_keyfile).arg(OPENSSL_EXTENSIONS_FILE).arg(subject);
+	subject = TQString("\"/CN=%1%2%3\"").arg(user.name).arg(openssldcForRealm(realmcfg.name)).arg(common_name);
+	command = TQString("openssl req -days %1 -new -out %2 -key %3 -config %4 -subj %5").arg(expirydays).arg(client_reqfile).arg(client_keyfile).arg(OPENSSL_EXTENSIONS_FILE).arg(subject);
 	if (system(command) < 0) {
 		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(certinfo.kerberosExpiryDays).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(OPENSSL_EXTENSIONS_FILE);
 	if (system(command) < 0) {
 		if (errstr) *errstr = TQString("Execution of \"%s\" failed").arg(command);
 		return -1;
diff --git a/src/libtdeldap.h b/src/libtdeldap.h
index f472c6c..90b44af 100644
--- a/src/libtdeldap.h
+++ b/src/libtdeldap.h
@@ -21,6 +21,7 @@
 #ifndef _LIBTDELDAP_H_
 #define _LIBTDELDAP_H_
 
+#include <stdint.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <ldap.h>
@@ -148,6 +149,19 @@
 
 typedef TQValueList<uid_t> UserList;
 typedef TQValueList<gid_t> GroupList;
+
+namespace PKICertificateStatus {
+	enum PKICertificateStatusEnum {
+		Invalid		= 0,
+		Valid		= 1,
+		Revoked		= 2
+	};
+}
+
+typedef TQValueList<TQByteArray> TQByteArrayList;
+
+typedef TQPair<uint32_t, TQByteArray> PKICertificateEntry;
+typedef TQValueList<PKICertificateEntry> PKICertificateEntryList;
 
 class LDAPCredentials
 {
@@ -329,6 +343,9 @@
 		TQString businessCategory;
 		TQString carLicense;
 		TQString notes;
+
+		// PKI
+		PKICertificateEntryList pkiCertificates;
 };
 
 class LDAPGroupInfo
@@ -501,6 +518,7 @@
 
 		int moveKerberosEntries(TQString newSuffix, TQString* errstr=0);
 		int writeCertificateFileIntoDirectory(TQByteArray cert, TQString attr, TQString* errstr=0);
+		int writePKICertificateFilesIntoDirectory(LDAPUserInfo user, TQString attr, TQString* errstr=0);
 
 		TQString getRealmCAMaster(TQString* errstr=0);
 		int setRealmCAMaster(TQString masterFQDN, TQString* errstr=0);
@@ -524,9 +542,9 @@
 		static int generatePublicKerberosCertificate(LDAPCertConfig certinfo, LDAPRealmConfig realmcfg);
 		static int generatePublicLDAPCertificate(LDAPCertConfig certinfo, LDAPRealmConfig realmcfg, uid_t ldap_uid, gid_t ldap_gid);
 
-		static int generateClientCertificatePair(LDAPCertConfig certinfo, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr=0);
+		static int generateClientCertificatePair(int expirydays, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr=0);
 		static int generateClientCertificatePrivateKey(LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString privateKeyFile, TQString *errstr=0);
-		static int generateClientCertificatePublicCertificate(LDAPCertConfig certinfo, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr=0);
+		static int generateClientCertificatePublicCertificate(int expirydays, LDAPUserInfo user, LDAPRealmConfig realmcfg, TQString signingPrivateKeyFile, TQString privateKeyFile, TQString publicCertFile, TQString *errstr=0);
 
 		static TQString ldapdnForRealm(TQString realm);
 		static TQString openssldcForRealm(TQString realm);