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 #include #include +#include #include #include @@ -37,6 +38,7 @@ #include #include #include +#include #include #include @@ -66,6 +68,11 @@ #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" #define LDAP_TERTIARY_FILE "/etc/libnss-ldap.conf" @@ -4559,6 +4566,8 @@ LDAPClientRealmConfig LDAPManager::loadClientRealmConfig(KSimpleConfig* config, 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 @@ int LDAPManager::saveClientRealmConfig(LDAPClientRealmConfig clientRealmConfig, 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 @@ int LDAPManager::writeNSSwitchFile(TQString *errstr) { 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 @@ int LDAPManager::writePAMFiles(LDAPPamConfig pamConfig, TQString *errstr) { 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"; @@ -4765,6 +4813,56 @@ int LDAPManager::writePAMFiles(LDAPPamConfig pamConfig, TQString *errstr) { } } + 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"); + } + } + } + return 0; } @@ -5374,6 +5472,8 @@ LDAPCertConfig::~LDAPCertConfig() { } 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 @@ class LDAPPamConfig ~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 @@ class LDAPManager : public TQObject { 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);