diff --git a/src/Makefile.am b/src/Makefile.am index 4d458e2..5d5b855 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ lib_LTLIBRARIES = libtdeldap.la include_HEADERS = libtdeldap.h ldappasswddlg.h libtdeldap_la_SOURCES = libtdeldap.cpp ldaplogindlgbase.ui ldaplogindlg.cpp ldappasswddlg.cpp -libtdeldap_la_LIBADD = -ltdeio $(LIB_TDEUI) -lldap $(LIB_QT) $(LIB_TDECORE) -ltdesu -llber -lkadm5clnt +libtdeldap_la_LIBADD = -ltdeio $(LIB_TDEUI) -lldap $(LIB_QT) $(LIB_TDECORE) -ltdesu -llber -lkadm5clnt -lkadm5srv libtdeldap_la_LDFLAGS = -version-info $(lt_current):$(lt_revision):$(lt_age) -no-undefined \ $(all_libraries) diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp index d240428..9f5f9a5 100644 --- a/src/libtdeldap.cpp +++ b/src/libtdeldap.cpp @@ -46,6 +46,35 @@ #include #include +#if 0 + #include + #include + #include + #include + #include + #include +#else + #include + + extern "C" { + // The following declaration was taken from hdb-protos.h + const char * + hdb_db_dir (krb5_context /*context*/); + + // The following declaration was taken from kadm5-private.h + kadm5_ret_t + kadm5_s_init_with_password_ctx ( + krb5_context /*context*/, + const char */*client_name*/, + const char */*password*/, + const char */*service_name*/, + kadm5_config_params */*realm_params*/, + unsigned long /*struct_version*/, + unsigned long /*api_version*/, + void **/*server_handle*/); + } +#endif + #include "libtdeldap.h" #include "ldaplogindlg.h" #include "ldappasswddlg.h" @@ -108,13 +137,13 @@ bool fileExists(const char* filename) { } } -LDAPManager::LDAPManager(TQString realm, TQString host, TQObject *parent, const char *name) : TQObject(parent, name), m_realm(realm), m_host(host), m_port(0), m_creds(0), m_ldap(0), m_krb5admHandle(0), m_krb5admKeytabFilename(0) +LDAPManager::LDAPManager(TQString realm, TQString host, TQObject *parent, const char *name) : TQObject(parent, name), m_realm(realm), m_host(host), m_port(0), m_creds(0), m_ldap(0), m_krb5admHandle(0), m_krb5admKeytabFilename(0), m_krb5admRealmName(0) { TQStringList domainChunks = TQStringList::split(".", realm.lower()); m_basedc = "dc=" + domainChunks.join(",dc="); } -LDAPManager::LDAPManager(TQString realm, TQString host, LDAPCredentials* creds, TQObject *parent, const char *name) : TQObject(parent, name), m_realm(realm), m_host(host), m_port(0), m_creds(creds), m_ldap(0), m_krb5admHandle(0), m_krb5admKeytabFilename(0) +LDAPManager::LDAPManager(TQString realm, TQString host, LDAPCredentials* creds, TQObject *parent, const char *name) : TQObject(parent, name), m_realm(realm), m_host(host), m_port(0), m_creds(creds), m_ldap(0), m_krb5admHandle(0), m_krb5admKeytabFilename(0), m_krb5admRealmName(0) { TQStringList domainChunks = TQStringList::split(".", realm.lower()); m_basedc = "dc=" + domainChunks.join(",dc="); @@ -1125,13 +1154,31 @@ int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) { admincreds.use_gssapi = true; } + bool use_local_socket = false; + if (m_host.startsWith("ldapi://")) { + use_local_socket = true; + } + TQString ticketFile; LDAPManager::getKerberosTicketList(TQString::null, &ticketFile); memset(¶ms, 0, sizeof(params)); - params.mask |= KADM5_CONFIG_REALM; - params.realm = const_cast(admincreds.realm.upper().ascii()); - + if (!use_local_socket) { + params.mask |= KADM5_CONFIG_REALM; + if (m_krb5admRealmName) { + free(m_krb5admRealmName); + } + if (admincreds.realm != "") { + m_krb5admRealmName = strdup(admincreds.realm.upper().ascii()); + } + else { + TQString defaultRealm; + fetchAndReadTDERealmList(&defaultRealm); + m_krb5admRealmName = strdup(defaultRealm.ascii()); + } + params.realm = m_krb5admRealmName; + } + TQString adminPrincipal = TQString::null; if (admincreds.username != "") { adminPrincipal = admincreds.username.lower() + "@" + admincreds.realm.upper(); @@ -1139,14 +1186,43 @@ int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) { krb5adm_ret = krb5_init_context(&m_krb5admContext); if (krb5adm_ret) { - if (errstr) *errstr = TQString("Internal Error

Failed to execute kadm5_init_krb5_context (code %1)").arg(krb5adm_ret); + if (errstr) *errstr = TQString("%1

Details:
Failed to execute kadm5_init_krb5_context (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); } else { - if (m_host.startsWith("ldapi://")) { + if (use_local_socket) { // Local bind - krb5adm_ret = kadm5_init_with_password_ctx(m_krb5admContext, KADM5_ADMIN_SERVICE, admincreds.password.data(), KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle); + + // Read KDC configuration files + int temp_ret; + char **files; + char* config_file; + temp_ret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(m_krb5admContext)); + if (temp_ret == -1) { + if (errstr) *errstr = i18n("Out of memory"); + } + + krb5adm_ret = krb5_prepend_config_files_default(config_file, &files); + if (krb5adm_ret) { + if (errstr) *errstr = i18n("%1

Details:
Failed to execute krb5_prepend_config_files_default (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); + } + + krb5adm_ret = krb5_set_config_files(m_krb5admContext, files); + krb5_free_config_files(files); + if(krb5adm_ret) { + if (errstr) *errstr = i18n("%1

Details:
Failed to execute krb5_set_config_files (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); + } + + // Bypass password quality checks + kadm5_setup_passwd_quality_check(m_krb5admContext, NULL, NULL); + krb5adm_ret = kadm5_add_passwd_quality_verifier(m_krb5admContext, NULL); + if (krb5adm_ret) { + if (errstr) *errstr = i18n("%1

Details:
Failed to execute kadm5_add_passwd_quality_verifier (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); + } + + // Initialize context + krb5adm_ret = kadm5_s_init_with_password_ctx(m_krb5admContext, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle); if (krb5adm_ret) { - if (errstr) *errstr = TQString("%1

Details:
Failed to execute kadm5_init_with_password (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); + if (errstr) *errstr = i18n("%1

Details:
Failed to execute kadm5_s_init_with_password_ctx (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); } } else if (admincreds.use_gssapi) { @@ -1157,14 +1233,14 @@ int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) { m_krb5admKeytabFilename = strdup(ticketFile.ascii()); krb5adm_ret = kadm5_init_with_skey_ctx(m_krb5admContext, KADM5_ADMIN_SERVICE, m_krb5admKeytabFilename, KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle); if (krb5adm_ret) { - if (errstr) *errstr = TQString("%1

Details:
Failed to execute kadm5_init_with_skey (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); + if (errstr) *errstr = i18n("%1

Details:
Failed to execute kadm5_init_with_skey (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); } } else { // Password authentication / bind - krb5adm_ret = kadm5_init_with_password_ctx(m_krb5admContext, adminPrincipal.ascii(), admincreds.password.data(), KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle); + krb5adm_ret = kadm5_init_with_password_ctx(m_krb5admContext, adminPrincipal.ascii(), admincreds.password.data(), KADM5_ADMIN_SERVICE, ¶ms, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle); if (krb5adm_ret) { - if (errstr) *errstr = TQString("%1

Details:
Failed to execute kadm5_init_with_password (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); + if (errstr) *errstr = i18n("%1

Details:
Failed to execute kadm5_init_with_password (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret); } } if (!krb5adm_ret) { @@ -1179,6 +1255,11 @@ int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) { int LDAPManager::unbindKAdmin(TQString *errstr) { if (m_krb5admKeytabFilename) { free(m_krb5admKeytabFilename); + m_krb5admKeytabFilename = NULL; + } + if (m_krb5admRealmName) { + free(m_krb5admRealmName); + m_krb5admRealmName = NULL; } kadm5_destroy(m_krb5admHandle); @@ -1203,12 +1284,12 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) { krb5_principal user_kadm5_principal; krb5adm_ret = krb5_parse_name(m_krb5admContext, user.name.ascii(), &user_kadm5_principal); if (krb5adm_ret) { - if (errstr) *errstr = TQString("%1

Details:
Failed to execute krb5_parse_name for user '%2' (code %3)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(user.name).arg(krb5adm_ret); + if (errstr) *errstr = i18n("%1

Details:
Failed to execute krb5_parse_name for user '%2' (code %3)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(user.name).arg(krb5adm_ret); } else { krb5adm_ret = kadm5_chpass_principal(m_krb5admHandle, user_kadm5_principal, user.new_password.data()); if (krb5adm_ret) { - if (errstr) *errstr = TQString("%1

Details:
Failed to execute kadm5_chpass_principal for user '%2' (code %3)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(user.name).arg(krb5adm_ret); + if (errstr) *errstr = i18n("%1

Details:
Failed to execute kadm5_chpass_principal for user '%2' (code %3)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(user.name).arg(krb5adm_ret); } else { // Success! diff --git a/src/libtdeldap.h b/src/libtdeldap.h index 9905eb6..ee685b4 100644 --- a/src/libtdeldap.h +++ b/src/libtdeldap.h @@ -612,6 +612,7 @@ class LDAPManager : public TQObject { krb5_context m_krb5admContext; void* m_krb5admHandle; char* m_krb5admKeytabFilename; + char* m_krb5admRealmName; }; #endif // _LIBTDELDAP_H_