svn commit: samba r11521 - in branches/SAMBA_4_0/source: auth/gensec libcli/ldap

abartlet at samba.org abartlet at samba.org
Sat Nov 5 11:02:39 GMT 2005


Author: abartlet
Date: 2005-11-05 11:02:37 +0000 (Sat, 05 Nov 2005)
New Revision: 11521

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=11521

Log:
Add in client support for checking supportedSASLmechanisms, and then
determining a mechanism to use.

Currently it doesn't to fallbacks like SPNEGO does, but this could be
added (to GENSEC, not to here).

This also adds a new function to GENSEC, which returns a list of SASL
names in our preference order (currently determined by the build
system of all things...).  

Also make the similar function used for OIDs in SPNEGO do the same.

This is all a very long-winded way of moving from a hard-coded NTLM to
GSS-SPNEGO in our SASL client...

Andrew Bartlett

Modified:
   branches/SAMBA_4_0/source/auth/gensec/gensec.c
   branches/SAMBA_4_0/source/auth/gensec/gensec_gssapi.c
   branches/SAMBA_4_0/source/auth/gensec/gensec_krb5.c
   branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c


Changeset:
Modified: branches/SAMBA_4_0/source/auth/gensec/gensec.c
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/gensec.c	2005-11-05 10:51:13 UTC (rev 11520)
+++ branches/SAMBA_4_0/source/auth/gensec/gensec.c	2005-11-05 11:02:37 UTC (rev 11521)
@@ -98,6 +98,71 @@
  * The list is in the exact order of the OIDs asked for, where available.
  */
 
+const struct gensec_security_ops **gensec_security_by_sasl(TALLOC_CTX *mem_ctx, 
+							  const char **sasl_names)
+{
+	const struct gensec_security_ops **backends_out;
+	const struct gensec_security_ops **backends;
+	int i, k, sasl_idx;
+	int num_backends_out = 0;
+	int num_backends;
+
+	if (!sasl_names) {
+		return NULL;
+	}
+
+	backends = gensec_security_all(&num_backends);
+
+	backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
+	if (!backends_out) {
+		return NULL;
+	}
+	backends_out[0] = NULL;
+
+	/* Find backends in our preferred order, by walking our list,
+	 * then looking in the supplied list */
+	for (i=0; i < num_backends; i++) {
+		for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
+			if (!backends[i]->sasl_name ||
+			    !(strcmp(backends[i]->sasl_name, 
+				     sasl_names[sasl_idx]) == 0)) {
+				continue;
+			}
+			
+			for (k=0; backends_out[k]; k++) {
+				if (backends_out[k] == backends[i]) {
+					break;
+				}
+			}
+			
+			if (k < num_backends_out) {
+				/* already in there */
+				continue;
+			}
+			
+			backends_out = talloc_realloc(mem_ctx, backends_out, 
+						      const struct gensec_security_ops *, 
+						      num_backends_out + 2);
+			if (!backends_out) {
+				return NULL;
+			}
+			
+			backends_out[num_backends_out] = backends[i];
+			num_backends_out++;
+			backends_out[num_backends_out] = NULL;
+		}
+	}
+	return backends_out;
+}
+
+/**
+ * Return a unique list of security subsystems from those specified in
+ * the OID list.  That is, where two OIDs refer to the same module,
+ * return that module only once 
+ *
+ * The list is in the exact order of the OIDs asked for, where available.
+ */
+
 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(TALLOC_CTX *mem_ctx, 
 								      const char **oid_strings,
 								      const char *skip)
@@ -121,15 +186,17 @@
 	backends_out[0].op = NULL;
 	backends_out[0].oid = NULL;
 
-	for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
-		if (strcmp(oid_strings[oid_idx], skip) == 0) {
+	/* Find backends in our preferred order, by walking our list,
+	 * then looking in the supplied list */
+	for (i=0; i < num_backends; i++) {
+		if (!backends[i]->oid) {
 			continue;
 		}
-
-		for (i=0; i < num_backends; i++) {
-			if (!backends[i]->oid) {
+		for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
+			if (strcmp(oid_strings[oid_idx], skip) == 0) {
 				continue;
 			}
+
 			for (j=0; backends[i]->oid[j]; j++) { 
 				if (!backends[i]->oid[j] ||
 				    !(strcmp(backends[i]->oid[j], 

Modified: branches/SAMBA_4_0/source/auth/gensec/gensec_gssapi.c
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/gensec_gssapi.c	2005-11-05 10:51:13 UTC (rev 11520)
+++ branches/SAMBA_4_0/source/auth/gensec/gensec_gssapi.c	2005-11-05 11:02:37 UTC (rev 11521)
@@ -965,6 +965,7 @@
 /* As a server, this could in theory accept any GSSAPI mech */
 static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
 	.name		= "gssapi_krb5",
+	.sasl_name      = "GSSAPI",
 	.auth_type	= DCERPC_AUTH_TYPE_KRB5,
 	.oid            = gensec_gssapi_krb5_oids,
 	.client_start   = gensec_gssapi_client_start,

Modified: branches/SAMBA_4_0/source/auth/gensec/gensec_krb5.c
===================================================================
--- branches/SAMBA_4_0/source/auth/gensec/gensec_krb5.c	2005-11-05 10:51:13 UTC (rev 11520)
+++ branches/SAMBA_4_0/source/auth/gensec/gensec_krb5.c	2005-11-05 11:02:37 UTC (rev 11521)
@@ -667,6 +667,7 @@
 
 static const struct gensec_security_ops gensec_fake_gssapi_krb5_security_ops = {
 	.name		= "fake_gssapi_krb5",
+	.sasl_name      = "GSSAPI",
 	.auth_type	= DCERPC_AUTH_TYPE_KRB5,
 	.oid            = gensec_krb5_oids,
 	.client_start   = gensec_fake_gssapi_krb5_client_start,

Modified: branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c	2005-11-05 10:51:13 UTC (rev 11520)
+++ branches/SAMBA_4_0/source/libcli/ldap/ldap_bind.c	2005-11-05 11:02:37 UTC (rev 11521)
@@ -145,6 +145,18 @@
 	DATA_BLOB input = data_blob(NULL, 0);
 	DATA_BLOB output = data_blob(NULL, 0);
 
+	struct ldap_message **sasl_mechs_msgs;
+	struct ldap_SearchResEntry *search;
+	int count, i;
+
+	const char **sasl_names;
+	const struct gensec_security_ops **mechs;
+	
+	static const char *supported_sasl_mech_attrs[] = {
+		"supportedSASLMechanisms", 
+		NULL 
+	};
+
 	status = gensec_client_start(conn, &conn->gensec, NULL);
 	if (!NT_STATUS_IS_OK(status)) {
 		DEBUG(0, ("Failed to start GENSEC engine (%s)\n", nt_errstr(status)));
@@ -174,16 +186,57 @@
 		goto failed;
 	}
 
-	status = gensec_start_mech_by_sasl_name(conn->gensec, "NTLM");
+	status = ildap_search(conn, "", LDAP_SEARCH_SCOPE_BASE, "", supported_sasl_mech_attrs, 
+			      False, &sasl_mechs_msgs);
 	if (!NT_STATUS_IS_OK(status)) {
-		DEBUG(1, ("Failed to set GENSEC client SPNEGO mechanism: %s\n",
+		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: %s\n", 
 			  nt_errstr(status)));
 		goto failed;
 	}
+	
+	count = ildap_count_entries(conn, sasl_mechs_msgs);
+	if (count != 1) {
+		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of replies: %d\n",
+			  count));
+		goto failed;
+	}
 
 	tmp_ctx = talloc_new(conn);
 	if (tmp_ctx == NULL) goto failed;
 
+	search = &sasl_mechs_msgs[0]->r.SearchResultEntry;
+	if (search->num_attributes != 1) {
+		DEBUG(1, ("Failed to inquire of target's available sasl mechs in rootdse search: wrong number of attributes: %d\n",
+			  search->num_attributes));
+		goto failed;
+	}
+
+	sasl_names = talloc_array(tmp_ctx, const char *, search->attributes[0].num_values + 1);
+	if (!sasl_names) {
+		DEBUG(1, ("talloc_arry(char *, %d) failed\n",
+			  count));
+		goto failed;
+	}
+		
+	for (i=0; i<search->attributes[0].num_values; i++) {
+		sasl_names[i] = (const char *)search->attributes[0].values[i].data;
+	}
+	sasl_names[i] = NULL;
+	
+	mechs = gensec_security_by_sasl(tmp_ctx, sasl_names);
+	if (!mechs || !mechs[0]) {
+		DEBUG(1, ("None of the %d proposed SASL mechs were acceptable\n",
+			  count));
+		goto failed;
+	}
+
+	status = gensec_start_mech_by_ops(conn->gensec, mechs[0]);
+	if (!NT_STATUS_IS_OK(status)) {
+		DEBUG(1, ("Failed to set GENSEC client mechanism: %s/%s %s\n",
+			  mechs[0]->name, mechs[0]->sasl_name, nt_errstr(status)));
+		goto failed;
+	}
+
 	while (1) {
 		NTSTATUS gensec_status;
 		struct ldap_message *response;



More information about the samba-cvs mailing list