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
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 \
$(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());
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());
m_basedc = "dc=" + domainChunks.join(",dc=");
@ -405,6 +405,10 @@ int LDAPManager::bind(TQString* errstr) {
}
int LDAPManager::unbind(bool force, TQString* errstr) {
if (m_krb5admHandle) {
unbindKAdmin();
}
if (!m_ldap) {
return 0;
}
@ -1094,12 +1098,23 @@ TQString LDAPManager::readFullLineFromPtyProcess(PtyProcess* proc) {
return result;
}
int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
if (user.new_password == "") {
return 0;
}
int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) {
int retcode = 1;
kadm5_ret_t krb5adm_ret;
kadm5_config_params params;
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 == "")) {
// Probably GSSAPI
// Get active ticket principal...
@ -1107,107 +1122,107 @@ int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0];
admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
}
TQCString command = "kadmin";
QCStringList args;
if (m_host.startsWith("ldapi://")) {
args << TQCString("-l") << TQCString("-r") << TQCString(admincreds.realm.upper());
TQString ticketFile;
LDAPManager::getKerberosTicketList(TQString::null, &ticketFile);
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 {
if (admincreds.username == "") {
args << TQCString("-r") << TQCString(admincreds.realm.upper());
if (m_host.startsWith("ldapi://")) {
// 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 {
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;
PtyProcess kadminProc;
kadminProc.exec(command, args);
prompt = readFullLineFromPtyProcess(&kadminProc);
prompt = prompt.stripWhiteSpace();
if (prompt == "kadmin>") {
command = TQCString("passwd "+user.name);
kadminProc.enableLocalEcho(false);
kadminProc.writeLine(command, true);
do { // Discard our own input
prompt = readFullLineFromPtyProcess(&kadminProc);
printf("(kadmin) '%s'\n", prompt.ascii());
} while ((prompt == TQString(command)) || (prompt == ""));
prompt = prompt.stripWhiteSpace();
if ((prompt.endsWith(" Password:")) && (prompt.startsWith(TQString(user.name + "@")))) {
kadminProc.enableLocalEcho(false);
kadminProc.writeLine(user.new_password, true);
do { // Discard our own input
prompt = readFullLineFromPtyProcess(&kadminProc);
printf("(kadmin) '%s'\n", prompt.ascii());
} while (prompt == "");
prompt = prompt.stripWhiteSpace();
if ((prompt.endsWith(" Password:")) && (prompt.startsWith("Verify"))) {
kadminProc.enableLocalEcho(false);
kadminProc.writeLine(user.new_password, true);
do { // Discard our own input
prompt = readFullLineFromPtyProcess(&kadminProc);
printf("(kadmin) '%s'\n", prompt.ascii());
} while (prompt == "");
prompt = prompt.stripWhiteSpace();
}
if (prompt.endsWith(" Password:")) {
if (admincreds.password == "") {
if (tqApp->type() != TQApplication::Tty) {
TQCString password;
int result = KPasswordDialog::getPassword(password, prompt);
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();
}
return retcode;
}
int LDAPManager::unbindKAdmin(TQString *errstr) {
if (m_krb5admKeytabFilename) {
free(m_krb5admKeytabFilename);
}
kadm5_destroy(m_krb5admHandle);
krb5_free_context(m_krb5admContext);
m_krb5admHandle = NULL;
return 0;
}
int LDAPManager::setPasswordForUser(LDAPUserInfo user, TQString *errstr) {
if (user.new_password == "") {
return 0;
}
int retcode;
kadm5_ret_t krb5adm_ret;
retcode = bindKAdmin(user, errstr);
if (retcode == 0) {
retcode = 1;
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<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);
}
else {
krb5adm_ret = kadm5_chpass_principal(m_krb5admHandle, user_kadm5_principal, user.new_password.data());
if (krb5adm_ret) {
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 (prompt != "kadmin>") {
if (errstr) *errstr = detailedKAdminErrorMessage(prompt);
kadminProc.enableLocalEcho(false);
kadminProc.writeLine("quit", true);
return 1;
else {
// Success!
retcode = 0;
}
// Success!
kadminProc.enableLocalEcho(false);
kadminProc.writeLine("quit", true);
return 0;
}
else if (prompt == "kadmin>") {
// Success!
kadminProc.enableLocalEcho(false);
kadminProc.writeLine("quit", true);
return 0;
// Clean up
krb5_free_principal(m_krb5admContext, user_kadm5_principal);
}
// Failure
if (errstr) *errstr = detailedKAdminErrorMessage(prompt);
kadminProc.enableLocalEcho(false);
kadminProc.writeLine("quit", true);
return 1;
unbindKAdmin();
}
if (errstr) *errstr = "Internal error. Verify that kadmin exists and can be executed.";
return 1; // Failure
return retcode;
}
TQString klistDateTimeToRFCDateTime(TQString datetime) {
@ -1746,6 +1761,7 @@ int LDAPManager::addMachineInfo(LDAPMachineInfo machine, TQString *errstr) {
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0];
admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
}
TQCString command = "kadmin";
@ -1871,6 +1887,7 @@ int LDAPManager::addServiceInfo(LDAPServiceInfo service, TQString *errstr) {
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0];
admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
}
TQCString command = "kadmin";
@ -2578,6 +2595,7 @@ int LDAPManager::exportKeytabForPrincipal(TQString principal, TQString fileName,
TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
admincreds.username = principalParts[0];
admincreds.realm = principalParts[1];
admincreds.use_gssapi = true;
}
TQCString command = "kadmin";

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

Loading…
Cancel
Save