Branch: master

c6eab472 2015-09-18 17:49:12 Timothy Pearson
Add PKCS methods
M src/libtdeldap.cpp
M src/libtdeldap.h
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index ea67fd6..15a0996 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
+#include <dirent.h>
 #include <netdb.h>
 #include <pwd.h>
 
@@ -37,6 +38,7 @@
 #include <tdesu/process.h>
 #include <ksslcertificate.h>
 #include <krfcdate.h>
+#include <tdecryptographiccarddevice.h>
 
 #include <ldap.h>
 #include <sasl/sasl.h>
@@ -65,6 +67,11 @@
 #define PAMD_COMMON_ACCOUNT "common-account"
 #define PAMD_COMMON_AUTH "common-auth"
 #define PAMD_COMMON_SESSION "common-session"
+
+#define PAMD_PKCS11_CONFIG_DIRECTORY "/etc/pam_pkcs11/"
+#define PAMD_PKCS11_CONFIG_FILE "pam_pkcs11.conf"
+
+#define PAMD_PKCS11_CERT_REHASH_COMMAND "pkcs11_make_hash_link"
 
 #define LDAP_FILE "/etc/ldap/ldap.conf"
 #define LDAP_SECONDARY_FILE "/etc/ldap.conf"
@@ -4559,6 +4566,8 @@
 	clientRealmConfig.passwordHash = config->readEntry("ConnectionPasswordHash", "exop");
 	clientRealmConfig.ignoredUsers = config->readEntry("ConnectionIgnoredUsers", DEFAULT_IGNORED_USERS_LIST);
 
+	clientRealmConfig.pamConfig.enable_pkcs11_login = config->readBoolEntry("EnablePKCS11Login", false);
+	clientRealmConfig.pamConfig.pkcs11_login_card_slot = config->readNumEntry("PKCS11LoginCardSlot", 0);
 	clientRealmConfig.pamConfig.enable_cached_credentials = config->readBoolEntry("EnableCachedCredentials", true);
 	clientRealmConfig.pamConfig.autocreate_user_directories_enable = config->readBoolEntry("EnableAutoUserDir", true);
 	clientRealmConfig.pamConfig.autocreate_user_directories_umask = config->readNumEntry("AutoUserDirUmask", 0022);
@@ -4589,6 +4598,8 @@
 	config->writeEntry("ConnectionPasswordHash", clientRealmConfig.passwordHash);
 	config->writeEntry("ConnectionIgnoredUsers", clientRealmConfig.ignoredUsers);
 
+	config->writeEntry("EnablePKCS11Login", clientRealmConfig.pamConfig.enable_pkcs11_login);
+	config->writeEntry("PKCS11LoginCardSlot", clientRealmConfig.pamConfig.pkcs11_login_card_slot);
 	config->writeEntry("EnableCachedCredentials", clientRealmConfig.pamConfig.enable_cached_credentials);
 	config->writeEntry("EnableAutoUserDir", clientRealmConfig.pamConfig.autocreate_user_directories_enable);
 	config->writeEntry("AutoUserDirUmask", clientRealmConfig.pamConfig.autocreate_user_directories_umask);
@@ -4685,6 +4696,37 @@
 	return 0;
 }
 
+int LDAPManager::rehashClientPKCSCertificates(TQString *errstr) {
+	// Save the original working directory
+	DIR* original_cwd = opendir(".");
+
+	// Change working directory to root certificate directory
+	if (chdir(KERBEROS_PKI_PUBLICDIR) < 0) {
+		if (errstr) {
+			*errstr = i18n("Could not change working directory to '%1'").arg(KERBEROS_PKI_PUBLICDIR);
+		}
+		return 1;
+	}
+
+	// Rehash certificates
+	if (system(PAMD_PKCS11_CERT_REHASH_COMMAND) < 0) {
+		if (errstr) {
+			*errstr = i18n("Could not rehash certificates in directory '%1'").arg(KERBEROS_PKI_PUBLICDIR);
+		}
+		return 1;
+	}
+
+	// Restore the original working directory
+	if (original_cwd) {
+		if (fchdir(dirfd(original_cwd)) < 0) {
+			// ERROR
+		}
+		closedir(original_cwd);
+	}
+
+	return 0;
+}
+
 int LDAPManager::writePAMFiles(LDAPPamConfig pamConfig, TQString *errstr) {
 	TQFile file(PAMD_DIRECTORY PAMD_COMMON_ACCOUNT);
 	if (file.open(IO_WriteOnly)) {
@@ -4713,11 +4755,17 @@
 		stream << "# All changes will be lost!\n";
 		stream << "\n";
 		stream << "auth [default=ignore success=ignore] pam_mount.so" << "\n";
-		stream << "auth sufficient pam_unix.so nullok try_first_pass" << "\n";
-		stream << "auth [default=ignore success=1 service_err=reset] pam_krb5.so ccache=/tmp/krb5cc_%u use_first_pass" << "\n";
+		stream << "auth [success=done new_authtok_reqd=done default=ignore] pam_unix.so nullok try_first_pass" << "\n";
 		if (pamConfig.enable_cached_credentials) {
-			stream << "auth [default=2 success=done] pam_ccreds.so action=validate use_first_pass" << "\n";
-			stream << "auth sufficient pam_ccreds.so action=store use_first_pass" << "\n";
+			stream << "auth [default=ignore success=1 service_err=reset] pam_krb5.so ccache=/tmp/krb5cc_%u use_first_pass" << "\n";
+			stream << "auth [default=1 success=done] pam_ccreds.so action=validate use_first_pass" << "\n";
+			stream << "auth [default=ignore success=done new_authtok_reqd=done] pam_ccreds.so action=store use_first_pass" << "\n";
+		}
+		else {
+			stream << "auth [default=ignore success=done new_authtok_reqd=done service_err=reset] pam_krb5.so ccache=/tmp/krb5cc_%u use_first_pass" << "\n";
+		}
+		if (pamConfig.enable_pkcs11_login) {
+			stream << "auth [default=ignore success=done new_authtok_reqd=done] pam_pkcs11.so" << "\n";
 		}
 		stream << "auth required pam_deny.so" << "\n";
 
@@ -4762,6 +4810,56 @@
 	else {
 		if (errstr) {
 			*errstr = i18n("Could not open file '%1' for writing").arg(file3.name());
+		}
+	}
+
+	if (pamConfig.enable_pkcs11_login) {
+		TQFile file4(PAMD_PKCS11_CONFIG_DIRECTORY PAMD_PKCS11_CONFIG_FILE);
+		if (file4.open(IO_WriteOnly)) {
+			TQTextStream stream( &file4 );
+
+			stream << "# This file was automatically generated by TDE\n";
+			stream << "# All changes will be lost!\n";
+			stream << "\n";
+			stream << "pam_pkcs11 {" << "\n";
+			stream << "	nullok = true;" << "\n";
+			stream << "	debug = false;" << "\n";
+			stream << "	use_first_pass = true;" << "\n";
+			stream << "	try_first_pass = false;" << "\n";
+			stream << "	use_authtok = false;" << "\n";
+			stream << "	use_pkcs11_module = opensc;" << "\n";
+			stream << "	pkcs11_module opensc {" << "\n";
+			stream << "		module = " << TDECryptographicCardDevice::pkcsProviderLibrary() << ";" << "\n";
+			stream << "		description = \"OpenSC PKCS#11 module\";" << "\n";
+			stream << "		slot_num = \"" << pamConfig.pkcs11_login_card_slot << "\";" << "\n";
+			stream << "		ca_dir = " KERBEROS_PKI_PUBLICDIR ";" << "\n";
+			stream << "		crl_dir = " KERBEROS_PKI_PUBLICDIR ";" << "\n";
+			stream << "		support_threads = false;" << "\n";
+			stream << "		cert_policy = ca,crl_auto,signature;" << "\n";
+			stream << "		token_type = \"Smart card\";" << "\n";
+			stream << "	}" << "\n";
+			stream << "	use_mappers = cn;" << "\n";
+			stream << "	mapper cn {" << "\n";
+			stream << "		debug = false;" << "\n";
+			stream << "		module = internal;" << "\n";
+			stream << "		ignorecase = true;" << "\n";
+			stream << "		mapfile = \"none\";" << "\n";
+			stream << "	}" << "\n";
+			stream << "}" << "\n";
+
+			file4.close();
+		}
+		else {
+			if (errstr) {
+				*errstr = i18n("Could not open file '%1' for writing").arg(file4.name());
+			}
+		}
+
+		// Rehash PKCS certificates
+		if (rehashClientPKCSCertificates() != 0) {
+			if (errstr) {
+				*errstr = i18n("Could not rehash PKCS certificates");
+			}
 		}
 	}
 
@@ -5374,6 +5472,8 @@
 }
 
 LDAPPamConfig::LDAPPamConfig() {
+	enable_pkcs11_login = false;
+	pkcs11_login_card_slot = 0;
 	enable_cached_credentials = true;
 	autocreate_user_directories_enable = true;
 	autocreate_user_directories_umask = 0;
diff --git a/src/libtdeldap.h b/src/libtdeldap.h
index 83428e3..5bd6173 100644
--- a/src/libtdeldap.h
+++ b/src/libtdeldap.h
@@ -239,6 +239,8 @@
 		~LDAPPamConfig();
 
 	public:
+		bool enable_pkcs11_login;
+		int pkcs11_login_card_slot;
 		bool enable_cached_credentials;
 		bool autocreate_user_directories_enable;
 		mode_t autocreate_user_directories_umask;
@@ -579,6 +581,7 @@
 		static int writeOpenSSLConfigurationFile(LDAPRealmConfig realmcfg, TQString *errstr=0);
 		static int writeOpenSSLConfigurationFile(LDAPRealmConfig realmcfg, LDAPUserInfo user, TQString opensslConfigFile, TQString caRootKeyFile=TQString::null, TQString caRootCertFile=TQString::null, TQString caRootDatabaseFile=TQString::null, TQString *errstr=0);
 		static int writeClientCronFiles(TQString *errstr=0);
+		static int rehashClientPKCSCertificates(TQString *errstr=0);
 		static int writePAMFiles(LDAPPamConfig pamConfig, TQString *errstr=0);
 
 		static int bondRealm(TQString adminUserName, const char * adminPassword, TQString adminRealm, TQString *errstr=0);