Start to move away from using the kadmin binary to using the kadmin client API

pull/1/head
Timothy Pearson 9 years ago
parent a619f64455
commit bd30e6c655

@ -7,7 +7,7 @@ lib_LTLIBRARIES = libtdeldap.la
include_HEADERS = libtdeldap.h ldappasswddlg.h include_HEADERS = libtdeldap.h ldappasswddlg.h
libtdeldap_la_SOURCES = libtdeldap.cpp ldaplogindlgbase.ui ldaplogindlg.cpp ldappasswddlg.cpp libtdeldap_la_SOURCES = libtdeldap.cpp ldaplogindlgbase.ui ldaplogindlg.cpp ldappasswddlg.cpp
libtdeldap_la_LIBADD = -ltdeio $(LIB_TDEUI) -lldap $(LIB_QT) $(LIB_TDECORE) -ltdesu -llber libtdeldap_la_LIBADD = -ltdeio $(LIB_TDEUI) -lldap $(LIB_QT) $(LIB_TDECORE) -ltdesu -llber -lkadm5clnt
libtdeldap_la_LDFLAGS = -version-info $(lt_current):$(lt_revision):$(lt_age) -no-undefined \ libtdeldap_la_LDFLAGS = -version-info $(lt_current):$(lt_revision):$(lt_age) -no-undefined \
$(all_libraries) $(all_libraries)

@ -108,13 +108,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) 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)
{ {
TQStringList domainChunks = TQStringList::split(".", realm.lower()); TQStringList domainChunks = TQStringList::split(".", realm.lower());
m_basedc = "dc=" + domainChunks.join(",dc="); 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) 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)
{ {
TQStringList domainChunks = TQStringList::split(".", realm.lower()); TQStringList domainChunks = TQStringList::split(".", realm.lower());
m_basedc = "dc=" + domainChunks.join(",dc="); m_basedc = "dc=" + domainChunks.join(",dc=");
@ -405,6 +405,10 @@ int LDAPManager::bind(TQString* errstr) {
} }
int LDAPManager::unbind(bool force, TQString* errstr) { int LDAPManager::unbind(bool force, TQString* errstr) {
if (m_krb5admHandle) {
unbindKAdmin();
}
if (!m_ldap) { if (!m_ldap) {
return 0; return 0;
} }
@ -1094,12 +1098,23 @@ TQString LDAPManager::readFullLineFromPtyProcess(PtyProcess* proc) {
return result; return result;
} }
int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) { int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) {
if (user.new_password == "") { int retcode = 1;
return 0;
} kadm5_ret_t krb5adm_ret;
kadm5_config_params params;
LDAPCredentials admincreds = currentLDAPCredentials(); LDAPCredentials admincreds = currentLDAPCredentials();
if (admincreds.use_gssapi) {
// FIXME
// Heimdal has issues parsing the keytab file, so for now just prompt for password
TQCString password;
int result = KPasswordDialog::getPassword(password, i18n("Enter password for %1").arg(admincreds.username));
if (result == KPasswordDialog::Accepted) {
admincreds.password = password;
admincreds.use_gssapi = false;
}
}
if ((admincreds.username == "") && (admincreds.password == "")) { if ((admincreds.username == "") && (admincreds.password == "")) {
// Probably GSSAPI // Probably GSSAPI
// Get active ticket principal... // Get active ticket principal...
@ -1107,107 +1122,107 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false); TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0]; admincreds.username = principalParts[0];
admincreds.realm = principalParts[1]; admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
} }
TQCString command = "kadmin"; TQString ticketFile;
QCStringList args; LDAPManager::getKerberosTicketList(TQString::null, &ticketFile);
if (m_host.startsWith("ldapi://")) {
args << TQCString("-l") << TQCString("-r") << TQCString(admincreds.realm.upper()); memset(&params, 0, sizeof(params));
params.mask |= KADM5_CONFIG_REALM;
params.realm = const_cast<char *>(admincreds.realm.upper().ascii());
TQString adminPrincipal = TQString::null;
if (admincreds.username != "") {
adminPrincipal = admincreds.username.lower() + "@" + admincreds.realm.upper();
}
krb5adm_ret = krb5_init_context(&m_krb5admContext);
if (krb5adm_ret) {
if (errstr) *errstr = TQString("Internal Error<p>Failed to execute kadm5_init_krb5_context (code %1)").arg(krb5adm_ret);
} }
else { else {
if (admincreds.username == "") { if (m_host.startsWith("ldapi://")) {
args << TQCString("-r") << TQCString(admincreds.realm.upper()); // Local bind
krb5adm_ret = kadm5_init_with_password_ctx(m_krb5admContext, KADM5_ADMIN_SERVICE, admincreds.password.data(), KADM5_ADMIN_SERVICE, &params, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle);
if (krb5adm_ret) {
if (errstr) *errstr = TQString("%1<p>Details:<br>Failed to execute kadm5_init_with_password (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
}
else if (admincreds.use_gssapi) {
// Keytab authentication / bind
if (m_krb5admKeytabFilename) {
free(m_krb5admKeytabFilename);
}
m_krb5admKeytabFilename = strdup(ticketFile.ascii());
krb5adm_ret = kadm5_init_with_skey_ctx(m_krb5admContext, KADM5_ADMIN_SERVICE, m_krb5admKeytabFilename, KADM5_ADMIN_SERVICE, &params, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle);
if (krb5adm_ret) {
if (errstr) *errstr = TQString("%1<p>Details:<br>Failed to execute kadm5_init_with_skey (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
} }
else { else {
args << TQCString("-p") << TQCString(admincreds.username.lower()+"@"+(admincreds.realm.upper())) << TQCString("-r") << TQCString(admincreds.realm.upper()); // Password authentication / bind
krb5adm_ret = kadm5_init_with_password_ctx(m_krb5admContext, adminPrincipal.ascii(), admincreds.password.data(), KADM5_ADMIN_SERVICE, &params, KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, &m_krb5admHandle);
if (krb5adm_ret) {
if (errstr) *errstr = TQString("%1<p>Details:<br>Failed to execute kadm5_init_with_password (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
}
}
if (!krb5adm_ret) {
// Success!
retcode = 0;
} }
} }
TQString prompt; return retcode;
PtyProcess kadminProc; }
kadminProc.exec(command, args);
prompt = readFullLineFromPtyProcess(&kadminProc); int LDAPManager::unbindKAdmin(TQString *errstr) {
prompt = prompt.stripWhiteSpace(); if (m_krb5admKeytabFilename) {
if (prompt == "kadmin>") { free(m_krb5admKeytabFilename);
command = TQCString("passwd "+user.name); }
kadminProc.enableLocalEcho(false);
kadminProc.writeLine(command, true); kadm5_destroy(m_krb5admHandle);
do { // Discard our own input krb5_free_context(m_krb5admContext);
prompt = readFullLineFromPtyProcess(&kadminProc);
printf("(kadmin) '%s'\n", prompt.ascii()); m_krb5admHandle = NULL;
} while ((prompt == TQString(command)) || (prompt == ""));
prompt = prompt.stripWhiteSpace(); return 0;
if ((prompt.endsWith(" Password:")) && (prompt.startsWith(TQString(user.name + "@")))) { }
kadminProc.enableLocalEcho(false);
kadminProc.writeLine(user.new_password, true); int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
do { // Discard our own input if (user.new_password == "") {
prompt = readFullLineFromPtyProcess(&kadminProc); return 0;
printf("(kadmin) '%s'\n", prompt.ascii()); }
} while (prompt == "");
prompt = prompt.stripWhiteSpace(); int retcode;
if ((prompt.endsWith(" Password:")) && (prompt.startsWith("Verify"))) { kadm5_ret_t krb5adm_ret;
kadminProc.enableLocalEcho(false);
kadminProc.writeLine(user.new_password, true); retcode = bindKAdmin(user, errstr);
do { // Discard our own input if (retcode == 0) {
prompt = readFullLineFromPtyProcess(&kadminProc); retcode = 1;
printf("(kadmin) '%s'\n", prompt.ascii()); krb5_principal user_kadm5_principal;
} while (prompt == ""); krb5adm_ret = krb5_parse_name(m_krb5admContext, user.name.ascii(), &user_kadm5_principal);
prompt = prompt.stripWhiteSpace(); if (krb5adm_ret) {
} if (errstr) *errstr = TQString("%1<p>Details:<br>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 (prompt.endsWith(" Password:")) { }
if (admincreds.password == "") { else {
if (tqApp->type() != TQApplication::Tty) { krb5adm_ret = kadm5_chpass_principal(m_krb5admHandle, user_kadm5_principal, user.new_password.data());
TQCString password; if (krb5adm_ret) {
int result = KPasswordDialog::getPassword(password, prompt); if (errstr) *errstr = TQString("%1<p>Details:<br>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 (result == KPasswordDialog::Accepted) {
admincreds.password = password;
}
}
else {
TQFile file;
file.open(IO_ReadOnly, stdin);
TQTextStream qtin(&file);
admincreds.password = qtin.readLine();
}
}
if (admincreds.password != "") {
kadminProc.enableLocalEcho(false);
kadminProc.writeLine(admincreds.password, true);
do { // Discard our own input
prompt = readFullLineFromPtyProcess(&kadminProc);
printf("(kadmin) '%s'\n", prompt.ascii());
} while (prompt == "");
prompt = prompt.stripWhiteSpace();
}
} }
if (prompt != "kadmin>") { else {
if (errstr) *errstr = detailedKAdminErrorMessage(prompt); // Success!
kadminProc.enableLocalEcho(false); retcode = 0;
kadminProc.writeLine("quit", true);
return 1;
} }
// Success! // Clean up
kadminProc.enableLocalEcho(false); krb5_free_principal(m_krb5admContext, user_kadm5_principal);
kadminProc.writeLine("quit", true);
return 0;
}
else if (prompt == "kadmin>") {
// Success!
kadminProc.enableLocalEcho(false);
kadminProc.writeLine("quit", true);
return 0;
} }
// Failure unbindKAdmin();
if (errstr) *errstr = detailedKAdminErrorMessage(prompt);
kadminProc.enableLocalEcho(false);
kadminProc.writeLine("quit", true);
return 1;
} }
if (errstr) *errstr = "Internal error. Verify that kadmin exists and can be executed."; return retcode;
return 1; // Failure
} }
TQString klistDateTimeToRFCDateTime(TQString datetime) { TQString klistDateTimeToRFCDateTime(TQString datetime) {
@ -1746,6 +1761,7 @@ int LDAPManager::addMachineInfo(LDAPMachineInfo machine, TQString *errstr) {
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false); TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0]; admincreds.username = principalParts[0];
admincreds.realm = principalParts[1]; admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
} }
TQCString command = "kadmin"; TQCString command = "kadmin";
@ -1871,6 +1887,7 @@ int LDAPManager::addServiceInfo(LDAPServiceInfo service, TQString *errstr) {
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false); TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0]; admincreds.username = principalParts[0];
admincreds.realm = principalParts[1]; admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
} }
TQCString command = "kadmin"; TQCString command = "kadmin";
@ -2578,6 +2595,7 @@ int LDAPManager::exportKeytabForPrincipal(TQString principal, TQString fileName,
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false); TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0]; admincreds.username = principalParts[0];
admincreds.realm = principalParts[1]; admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
} }
TQCString command = "kadmin"; TQCString command = "kadmin";

@ -25,6 +25,7 @@
#include <unistd.h> #include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <ldap.h> #include <ldap.h>
#include <kadm5/admin.h>
#include <tqobject.h> #include <tqobject.h>
#include <tqstring.h> #include <tqstring.h>
@ -588,6 +589,8 @@ class LDAPManager : public TQObject {
static int unbondRealm(LDAPRealmConfig realmcfg, TQString adminUserName, const char * adminPassword, TQString adminRealm, TQString *errstr=0); static int unbondRealm(LDAPRealmConfig realmcfg, TQString adminUserName, const char * adminPassword, TQString adminRealm, TQString *errstr=0);
private: private:
int bindKAdmin(LDAPUserInfo user, TQString *errstr=0);
int unbindKAdmin(TQString *errstr=0);
LDAPUserInfo parseLDAPUserRecord(LDAPMessage* entry); LDAPUserInfo parseLDAPUserRecord(LDAPMessage* entry);
LDAPGroupInfo parseLDAPGroupRecord(LDAPMessage* entry); LDAPGroupInfo parseLDAPGroupRecord(LDAPMessage* entry);
LDAPMachineInfo parseLDAPMachineRecord(LDAPMessage* entry); LDAPMachineInfo parseLDAPMachineRecord(LDAPMessage* entry);
@ -604,6 +607,11 @@ class LDAPManager : public TQObject {
TQString m_basedc; TQString m_basedc;
LDAPCredentials* m_creds; LDAPCredentials* m_creds;
LDAP *m_ldap; LDAP *m_ldap;
// kadmin interface
krb5_context m_krb5admContext;
void* m_krb5admHandle;
char* m_krb5admKeytabFilename;
}; };
#endif // _LIBTDELDAP_H_ #endif // _LIBTDELDAP_H_

Loading…
Cancel
Save