bfd5b6
From a4c35124b5c83603333ee7518d0783ff708e86df Mon Sep 17 00:00:00 2001
bfd5b6
From: Sumit Bose <sbose@redhat.com>
bfd5b6
Date: Fri, 11 Oct 2019 16:39:25 +0200
bfd5b6
Subject: [PATCH 1/2] Use GSS-SPNEGO if available
bfd5b6
bfd5b6
Currently adcli uses the GSSAPI SASL mechanism for LDAP authentication
bfd5b6
and to establish encryption. While this works in general it does not
bfd5b6
handle some of the more advanced features which can be required by AD
bfd5b6
DCs.
bfd5b6
bfd5b6
The GSS-SPNEGO mechanism can handle them and is used with this patch by
bfd5b6
adcli if the AD DC indicates that it supports it.
bfd5b6
bfd5b6
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1762420
bfd5b6
---
bfd5b6
 library/adconn.c | 35 ++++++++++++++++++++++++++++++++++-
bfd5b6
 library/adconn.h |  3 +++
bfd5b6
 2 files changed, 37 insertions(+), 1 deletion(-)
bfd5b6
bfd5b6
diff --git a/library/adconn.c b/library/adconn.c
bfd5b6
index f6c23d3..a3f4548 100644
bfd5b6
--- a/library/adconn.c
bfd5b6
+++ b/library/adconn.c
bfd5b6
@@ -77,6 +77,7 @@ struct _adcli_conn_ctx {
bfd5b6
 	char *default_naming_context;
bfd5b6
 	char *configuration_naming_context;
bfd5b6
 	char **supported_capabilities;
bfd5b6
+	char **supported_sasl_mechs;
bfd5b6
 
bfd5b6
 	/* Connect state */
bfd5b6
 	LDAP *ldap;
bfd5b6
@@ -845,6 +846,7 @@ connect_and_lookup_naming (adcli_conn *conn,
bfd5b6
 		"defaultNamingContext",
bfd5b6
 		"configurationNamingContext",
bfd5b6
 		"supportedCapabilities",
bfd5b6
+		"supportedSASLMechanisms",
bfd5b6
 		NULL
bfd5b6
 	};
bfd5b6
 
bfd5b6
@@ -897,6 +899,11 @@ connect_and_lookup_naming (adcli_conn *conn,
bfd5b6
 		                                                         "supportedCapabilities");
bfd5b6
 	}
bfd5b6
 
bfd5b6
+	if (conn->supported_sasl_mechs == NULL) {
bfd5b6
+		conn->supported_sasl_mechs = _adcli_ldap_parse_values (ldap, results,
bfd5b6
+		                                                       "supportedSASLMechanisms");
bfd5b6
+	}
bfd5b6
+
bfd5b6
 	ldap_msgfree (results);
bfd5b6
 
bfd5b6
 	if (conn->default_naming_context == NULL) {
bfd5b6
@@ -1022,6 +1029,7 @@ authenticate_to_directory (adcli_conn *conn)
bfd5b6
 	OM_uint32 minor;
bfd5b6
 	ber_len_t ssf;
bfd5b6
 	int ret;
bfd5b6
+	const char *mech = "GSSAPI";
bfd5b6
 
bfd5b6
 	if (conn->ldap_authenticated)
bfd5b6
 		return ADCLI_SUCCESS;
bfd5b6
@@ -1038,7 +1046,11 @@ authenticate_to_directory (adcli_conn *conn)
bfd5b6
 	ret = ldap_set_option (conn->ldap, LDAP_OPT_X_SASL_SSF_MIN, &ssf;;
bfd5b6
 	return_unexpected_if_fail (ret == 0);
bfd5b6
 
bfd5b6
-	ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, "GSSAPI", NULL, NULL,
bfd5b6
+	if (adcli_conn_server_has_sasl_mech (conn, "GSS-SPNEGO")) {
bfd5b6
+		mech =  "GSS-SPNEGO";
bfd5b6
+	}
bfd5b6
+
bfd5b6
+	ret = ldap_sasl_interactive_bind_s (conn->ldap, NULL, mech, NULL, NULL,
bfd5b6
 	                                    LDAP_SASL_QUIET, sasl_interact, NULL);
bfd5b6
 
bfd5b6
 	/* Clear the credential cache GSSAPI to use (for this thread) */
bfd5b6
@@ -1231,6 +1243,7 @@ conn_free (adcli_conn *conn)
bfd5b6
 	free (conn->default_naming_context);
bfd5b6
 	free (conn->configuration_naming_context);
bfd5b6
 	_adcli_strv_free (conn->supported_capabilities);
bfd5b6
+	_adcli_strv_free (conn->supported_sasl_mechs);
bfd5b6
 
bfd5b6
 	free (conn->computer_name);
bfd5b6
 	free (conn->host_fqdn);
bfd5b6
@@ -1593,6 +1606,26 @@ adcli_conn_server_has_capability (adcli_conn *conn,
bfd5b6
 	return 0;
bfd5b6
 }
bfd5b6
 
bfd5b6
+bool
bfd5b6
+adcli_conn_server_has_sasl_mech (adcli_conn *conn,
bfd5b6
+                                 const char *mech)
bfd5b6
+{
bfd5b6
+	int i;
bfd5b6
+
bfd5b6
+	return_val_if_fail (conn != NULL, false);
bfd5b6
+	return_val_if_fail (mech != NULL, false);
bfd5b6
+
bfd5b6
+	if (!conn->supported_sasl_mechs)
bfd5b6
+		return false;
bfd5b6
+
bfd5b6
+	for (i = 0; conn->supported_sasl_mechs[i] != NULL; i++) {
bfd5b6
+		if (strcasecmp (mech, conn->supported_sasl_mechs[i]) == 0)
bfd5b6
+			return true;
bfd5b6
+	}
bfd5b6
+
bfd5b6
+	return false;
bfd5b6
+}
bfd5b6
+
bfd5b6
 bool adcli_conn_is_writeable (adcli_conn *conn)
bfd5b6
 {
bfd5b6
 	disco_dance_if_necessary (conn);
bfd5b6
diff --git a/library/adconn.h b/library/adconn.h
bfd5b6
index 13cfd32..8e88045 100644
bfd5b6
--- a/library/adconn.h
bfd5b6
+++ b/library/adconn.h
bfd5b6
@@ -146,6 +146,9 @@ void                adcli_conn_set_krb5_conf_dir     (adcli_conn *conn,
bfd5b6
 int                 adcli_conn_server_has_capability (adcli_conn *conn,
bfd5b6
                                                       const char *capability);
bfd5b6
 
bfd5b6
+bool                adcli_conn_server_has_sasl_mech  (adcli_conn *conn,
bfd5b6
+                                                      const char *mech);
bfd5b6
+
bfd5b6
 bool                adcli_conn_is_writeable          (adcli_conn *conn);
bfd5b6
 
bfd5b6
 #endif /* ADCONN_H_ */
bfd5b6
-- 
bfd5b6
2.21.1
bfd5b6