Blame 0004-Use-GSS-SPNEGO-if-available.patch

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