Branch: master

11869fce 2015-09-29 00:35:24 Timothy Pearson
Move keytab export to native Heimdal API
M src/libtdeldap.cpp
M src/libtdeldap.h
diff --git a/src/libtdeldap.cpp b/src/libtdeldap.cpp
index 93ec360..19812d5 100644
--- a/src/libtdeldap.cpp
+++ b/src/libtdeldap.cpp
@@ -1140,13 +1140,19 @@
 	return result;
 }
 
-int LDAPManager::bindKAdmin(TQString *errstr) {
+int LDAPManager::bindKAdmin(LDAPCredentials *administrativeCredentials, TQString *errstr) {
 	int retcode = 1;
 
 	kadm5_ret_t krb5adm_ret;
 	kadm5_config_params params;
 
-	LDAPCredentials admincreds = currentLDAPCredentials();
+	LDAPCredentials admincreds;
+	if (administrativeCredentials) {
+		admincreds = *administrativeCredentials;
+	}
+	else {
+		admincreds = currentLDAPCredentials();
+	}
 	if (admincreds.use_gssapi) {
 		// FIXME
 		// Heimdal has issues parsing the keytab file, so for now just prompt for password
@@ -1291,7 +1297,14 @@
 	int retcode;
 	kadm5_ret_t krb5adm_ret;
 
-	retcode = bindKAdmin(errstr);
+	bool kadmin_unbind_needed = false;
+	if (m_krb5admHandle) {
+		retcode = 0;
+	}
+	else {
+		retcode = bindKAdmin(NULL, errstr);
+		kadmin_unbind_needed = true;
+	}
 	if (retcode == 0) {
 		retcode = 1;
 		krb5_principal user_kadm5_principal;
@@ -1313,8 +1326,10 @@
 			krb5_free_principal(m_krb5admContext, user_kadm5_principal);
 		}
 
-		unbindKAdmin();
-		unbind(true);	// Using kadmin can disrupt our LDAP connection
+		if (kadmin_unbind_needed) {
+			unbindKAdmin();
+			unbind(true);	// Using kadmin can disrupt our LDAP connection
+		}
 	}
 
 	return retcode;
@@ -1843,147 +1858,151 @@
 }
 
 int LDAPManager::kAdminAddNewPrincipal(TQString principalName, TQString newPassword, TQString *errstr) {
-	if (bind() < 0) {
-		return -1;
+	int retcode;
+	kadm5_ret_t krb5adm_ret;
+	int i;
+	char* password = NULL;
+
+	bool kadmin_unbind_needed = false;
+	if (m_krb5admHandle) {
+		retcode = 0;
 	}
 	else {
-		int retcode;
-		kadm5_ret_t krb5adm_ret;
-		int i;
-		char* password = NULL;
+		retcode = bindKAdmin(NULL, errstr);
+		kadmin_unbind_needed = true;
+	}
+	if (retcode == 0) {
+		retcode = 1;
+		bool generate_password;
+		if (newPassword == "") {
+			generate_password = true;
+		}
+		else {
+			generate_password = false;
+			password = strdup(newPassword.ascii());
+		}
 
-		retcode = bindKAdmin(errstr);
-		if (retcode == 0) {
-			retcode = 1;
-			bool generate_password;
-			if (newPassword == "") {
-				generate_password = true;
-			}
-			else {
-				generate_password = false;
-				password = strdup(newPassword.ascii());
-			}
+		// Construct and add new principal record
+		kadm5_principal_ent_rec principal_record;
+		kadm5_principal_ent_rec default_record;
+		kadm5_principal_ent_rec *default_entry = NULL;
+		krb5_principal principal_entry = NULL;
+		int mask = 0;
 
-			// Construct and add new principal record
-			kadm5_principal_ent_rec principal_record;
-			kadm5_principal_ent_rec default_record;
-			kadm5_principal_ent_rec *default_entry = NULL;
-			krb5_principal principal_entry = NULL;
-			int mask = 0;
+		memset(&principal_record, 0, sizeof(principal_record));
+		krb5adm_ret = krb5_parse_name(m_krb5admContext, principalName.ascii(), &principal_entry);
+		if (krb5adm_ret) {
+			if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute krb5_parse_name (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
+		}
+		principal_record.principal = principal_entry;
+		mask |= KADM5_PRINCIPAL;
 
-			memset(&principal_record, 0, sizeof(principal_record));
-			krb5adm_ret = krb5_parse_name(m_krb5admContext, principalName.ascii(), &principal_entry);
-			if (krb5adm_ret) {
-				if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute krb5_parse_name (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
-			}
-			principal_record.principal = principal_entry;
-			mask |= KADM5_PRINCIPAL;
+		default_entry = &default_record;
+		krb5adm_ret = kadm5_get_default_principal_info(m_krb5admContext, m_krb5admHandle, principal_entry, default_entry);
+		if (krb5adm_ret) {
+			default_entry = NULL;
+			if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_get_default_principal_info (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
+		}
+		else {
+			// Use defaults
+			principal_record.max_life = default_entry->max_life;
+			principal_record.max_renewable_life = default_entry->max_renewable_life;
+			principal_record.princ_expire_time = default_entry->princ_expire_time;
+			principal_record.pw_expiration = default_entry->pw_expiration;
+			principal_record.attributes = default_entry->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX;
+			principal_record.policy = strdup(default_entry->policy);
 
-			default_entry = &default_record;
-			krb5adm_ret = kadm5_get_default_principal_info(m_krb5admContext, m_krb5admHandle, principal_entry, default_entry);
-			if (krb5adm_ret) {
-				default_entry = NULL;
-				if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_get_default_principal_info (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
-			}
-			else {
-				// Use defaults
-				principal_record.max_life = default_entry->max_life;
-				principal_record.max_renewable_life = default_entry->max_renewable_life;
-				principal_record.princ_expire_time = default_entry->princ_expire_time;
-				principal_record.pw_expiration = default_entry->pw_expiration;
-				principal_record.attributes = default_entry->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX;
-				principal_record.policy = strdup(default_entry->policy);
+			if (generate_password) {
+				const char charset[] =
+					"@$%&*()-+=:,/<>?0123456789"
+					"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+					"abcdefghijklmnopqrstuvwxyz";
+				const size_t max_index = (sizeof(charset) - 2);
 
-				if (generate_password) {
-					const char charset[] =
-						"@$%&*()-+=:,/<>?0123456789"
-						"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-						"abcdefghijklmnopqrstuvwxyz";
-					const size_t max_index = (sizeof(charset) - 2);
-
-					TQFile randomNode("/dev/urandom");
-					if (randomNode.open(IO_ReadOnly)) {
-						password = (char*)malloc(sizeof(char) * KRB5_ANK_RANDOM_PASSWORD_LENGTH);
-						if (password) {
-							if (randomNode.readBlock(password, KRB5_ANK_RANDOM_PASSWORD_LENGTH) < KRB5_ANK_RANDOM_PASSWORD_LENGTH) {
-								free(password);
-								password = NULL;
-							}
-							else {
-								for (i = 0; i < KRB5_ANK_RANDOM_PASSWORD_LENGTH - 1; i++) {
-									while ((unsigned char)password[i] > max_index) {
-										password[i] -= max_index;
-									}
-									password[i] = charset[(int)password[i]];
-								}
-								password[i] = 0;
-							}
-						}
-						randomNode.close();
-					}
+				TQFile randomNode("/dev/urandom");
+				if (randomNode.open(IO_ReadOnly)) {
+					password = (char*)malloc(sizeof(char) * KRB5_ANK_RANDOM_PASSWORD_LENGTH);
 					if (password) {
-						principal_record.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
-						mask |= KADM5_ATTRIBUTES;
+						if (randomNode.readBlock(password, KRB5_ANK_RANDOM_PASSWORD_LENGTH) < KRB5_ANK_RANDOM_PASSWORD_LENGTH) {
+							free(password);
+							password = NULL;
+						}
+						else {
+							for (i = 0; i < KRB5_ANK_RANDOM_PASSWORD_LENGTH - 1; i++) {
+								while ((unsigned char)password[i] > max_index) {
+									password[i] -= max_index;
+								}
+								password[i] = charset[(int)password[i]];
+							}
+							password[i] = 0;
+						}
 					}
-					else {
-						if (errstr) *errstr = i18n("Unable to generate random password");
-					}
+					randomNode.close();
 				}
-
 				if (password) {
-					krb5adm_ret = kadm5_create_principal(m_krb5admHandle, &principal_record, mask, password);
-					if (krb5adm_ret) {
-						if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_create_principal (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
-					}
-					else {
-						if (generate_password) {
-							krb5_keyblock *new_keys;
-							int key_count;
-							krb5adm_ret = kadm5_randkey_principal(m_krb5admHandle, principal_entry, &new_keys, &key_count);
-							if (krb5adm_ret) {
-								key_count = 0;
-							}
-							for (i = 0; i < key_count; i++) {
-								krb5_free_keyblock_contents(m_krb5admContext, &new_keys[i]);
-							}
-							if (key_count > 0) {
-								free(new_keys);
-							}
-							kadm5_get_principal(m_krb5admHandle, principal_entry, &principal_record, KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
-							krb5_free_principal(m_krb5admContext, principal_entry);
-							principal_entry = principal_record.principal;
-							principal_record.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
-							principal_record.kvno = 1;
-							krb5adm_ret = kadm5_modify_principal(m_krb5admHandle, &principal_record, KADM5_ATTRIBUTES | KADM5_KVNO);
-							if (krb5adm_ret) {
-								if (errstr) *errstr = i18n("%1<p>Details:<br>Failed to execute kadm5_modify_principal (code %2)").arg(krb5_get_error_message(m_krb5admContext, krb5adm_ret)).arg(krb5adm_ret);
-							}
-							else {
-								retcode = 0;
-							}
+					principal_record.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+					mask |= KADM5_ATTRIBUTES;
 ** Diff limit reached (max: 250 lines) **