summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-27 18:07:40 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2015-09-27 18:07:40 -0500
commitbd30e6c65567795863eec5e3e9ac57d6b2b43207 (patch)
treee574a52022ced221b5988761ffd0cde22b9bf5fb
parenta619f64455bf3cd5715505b0cab057ca920fc7a0 (diff)
downloadlibtdeldap-bd30e6c6.tar.gz
libtdeldap-bd30e6c6.zip
Start to move away from using the kadmin binary to using the kadmin client API
-rw-r--r--src/Makefile.am2
-rw-r--r--src/libtdeldap.cpp200
-rw-r--r--src/libtdeldap.h8
3 files changed, 118 insertions, 92 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index edab92e..4d458e2 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
+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)
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index 1721bc5..d240428 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -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";
diff --git a/src/libtdeldap.h b/src/libtdeldap.h
index ee70ad2..9905eb6 100644
--- a/src/libtdeldap.h
+++ b/src/libtdeldap.h
@@ -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_