Branch: master

0fbc17ac 2015-09-28 17:18:35 Timothy Pearson
Convert machine add to kadmin API
M src/libtdeldap.cpp
M src/libtdeldap.h
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index 9f5f9a5..a227582 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -46,34 +46,15 @@
 #include <sys/time.h>
 #include <errno.h>
 
-#if 0
-	#include <sys/socket.h>
-	#include <sys/un.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+extern "C" {
 	#include <hdb.h>
 	#include <kadm5/admin.h>
 	#include <kadm5/private.h>
 	#include <kadm5/kadm5-private.h>
-#else
-	#include <kadm5/admin.h>
-
-	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"
@@ -89,6 +70,9 @@
 // FIXME
 // This assumes Debian!
 #define KRB5_FILE "/etc/krb5.conf"
+
+//#define KRB5_ANK_RANDOM_PASSWORD_LENGTH 1024
+#define KRB5_ANK_RANDOM_PASSWORD_LENGTH 512
 
 #define NSSWITCH_FILE "/etc/nsswitch.conf"
 
@@ -135,6 +119,19 @@
 	else {
 		return true;
 	}
+}
+
+static kadm5_ret_t kadm5_get_default_principal_info(krb5_context context, void* handle, krb5_principal princ, kadm5_principal_ent_t def) {
+	kadm5_ret_t ret;
+	krb5_principal def_principal;
+	krb5_const_realm realm = krb5_principal_get_realm(context, princ);
+	ret = krb5_make_principal(context, &def_principal, realm, "default", NULL);
+	if (ret) {
+		return ret;
+	}
+	ret = kadm5_get_principal(handle, def_principal, def, KADM5_PRINCIPAL_NORMAL_MASK);
+	krb5_free_principal(context, def_principal);
+	return ret;
 }
 
 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)
@@ -196,9 +193,24 @@
 	return m_realm;
 }
 
-LDAPCredentials LDAPManager::currentLDAPCredentials() {
+LDAPCredentials LDAPManager::currentLDAPCredentials(bool inferGSSAPIData) {
 	if (m_creds) {
-		return *m_creds;
+		if (inferGSSAPIData) {
+			LDAPCredentials credentials = *m_creds;
+			if ((credentials.username == "") && (credentials.password == "")) {
+				// Probably GSSAPI
+				// Get active ticket principal...
+				KerberosTicketInfoList tickets = LDAPManager::getKerberosTicketList();
+				TQStringList principalParts = TQStringList::split("@", tickets[0].cachePrincipal, false);
+				credentials.username = principalParts[0];
+				credentials.realm = principalParts[1];
+				credentials.use_gssapi = true;
+			}
+			return credentials;
+		}
+		else {
+			return *m_creds;
+		}
 	}
 	else {
 		return LDAPCredentials();
@@ -346,8 +358,9 @@
 					return -1;
 				}
 				struct berval anoncred;
-				anoncred.bv_val = "";
-				anoncred.bv_len = strlen("");
+				TQCString anonpass = "";
+				anoncred.bv_val = anonpass.data();
+				anoncred.bv_len = anonpass.length();
 				retcode = ldap_sasl_bind_s(ldapconn, "", mechanism, &anoncred, NULL, NULL, NULL);
 				if (retcode == LDAP_SUCCESS ) {
 					// Look for the DN for the specified user
@@ -372,7 +385,7 @@
 					}
 					// clean up
 					ldap_msgfree(msg);
-	
+
 					// All done!
 					ldap_unbind_ext_s(ldapconn, NULL, NULL);
 				}
@@ -727,10 +740,10 @@
 			for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
 				users.append(parseLDAPUserRecord(entry));
 			}
-		
+
 			// clean up
 			ldap_msgfree(msg);
-	
+
 			if (mretcode) *mretcode = 0;
 			return users;
 		}
@@ -743,7 +756,7 @@
 			LDAPControl* pageControl = NULL;
 			LDAPControl* serverControls[2] = { NULL, NULL };
 			LDAPControl** returnedControls = NULL;
-	
+
 			do {
 				retcode = ldap_create_page_control(m_ldap, pageSize, &cookie, pagingCriticality, &pageControl);
 				if (retcode != LDAP_SUCCESS) {
@@ -791,7 +804,7 @@
 				else {
 					morePages = false;
 				}
-	
+
 				if (returnedControls != NULL) {
 					ldap_controls_free(returnedControls);
 					returnedControls = NULL;
@@ -799,17 +812,17 @@
 				serverControls[0] = NULL;
 				ldap_control_free(pageControl);
 				pageControl = NULL;
-	
+
 				// Iterate through the returned entries
 				LDAPMessage* entry;
 				for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
 					users.append(parseLDAPUserRecord(entry));
 				}
-			
+
 				// clean up
 				ldap_msgfree(msg);
 			} while (morePages);
-	
+
 			if (mretcode) *mretcode = 0;
 			return users;
 		}
@@ -838,7 +851,7 @@
 		for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
 			userinfo = parseLDAPUserRecord(entry);
 		}
-		
+
 		// clean up
 		ldap_msgfree(msg);
 
@@ -869,7 +882,7 @@
 		for(entry = ldap_first_entry(m_ldap, msg); entry != NULL; entry = ldap_next_entry(m_ldap, entry)) {
 			groupinfo = parseLDAPGroupRecord(entry);
 		}
-		
+
 		// clean up
 		ldap_msgfree(msg);
 
@@ -1127,7 +1140,7 @@
 	return result;
 }
 
-int LDAPManager::bindKAdmin(LDAPUserInfo user, TQString *errstr) {
+int LDAPManager::bindKAdmin(TQString *errstr) {
 	int retcode = 1;
 
 	kadm5_ret_t krb5adm_ret;
@@ -1186,7 +1199,7 @@
 
 	krb5adm_ret = krb5_init_context(&m_krb5admContext);
 	if (krb5adm_ret) {
-		if (errstr) *errstr = TQString("%1<p>Details:<br>Failed to execute kadm5_init_krb5_context (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
+		if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_init_krb5_context (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
 	}
 	else {
 		if (use_local_socket) {
@@ -1205,7 +1218,7 @@
 			if (krb5adm_ret) {
 				if (errstr) *errstr = i18n("%1<p>Details:<br>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) {
@@ -1278,7 +1291,7 @@
 	int retcode;
 	kadm5_ret_t krb5adm_ret;
 
-	retcode = bindKAdmin(user, errstr);
+	retcode = bindKAdmin(errstr);
 	if (retcode == 0) {
 		retcode = 1;
 		krb5_principal user_kadm5_principal;
@@ -1301,6 +1314,7 @@
 		}
 
 		unbindKAdmin();
+		unbind(true);	// Using kadmin can disrupt our LDAP connection
 	}
 
 	return retcode;
@@ -1833,6 +1847,147 @@
 		return -1;
 	}
 	else {
+		int retcode;
+		kadm5_ret_t krb5adm_ret;
+		int i;
+		char* password = NULL;
+
+		retcode = bindKAdmin(errstr);
+		if (retcode == 0) {
+			retcode = 1;
+			bool generate_password;
+			if (machine.newPassword == "") {
 ** Diff limit reached (max: 250 lines) **