[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Heimdal PATCH] LDAP backend support for OpenLDAP 2.1.x



Hi!

The Heimdal hdb-ldap support is not yet updated to support binding to
the Open LDAP server version 2.1.x using the Unix IPC ldapi:/// method.

The current implementation only has support to work with OpenLDAP 2.0.x,
but this is a old version of the Open LDAP software.

Howard Chu provided me the modifications to bind to the Open LDAP server
version 2.1.16.

However this modification is not working for OpenLDAP 2.1.17. I figure
out the reason, and there is a difference in the sasl.c for the
ldap_sasl_bind_s() function call between OpenLDAP 2.1.16 and 2.1.17. 

The difference is in the struct berval bv. This is interpreted as NULL
credentials in revision 2.1.17, but not in 2.1.16. The solution is
initialize this berval structure in the follow way:

struct berval bv = { 0, "" }

instead of:
struct berval bv = { 0, NULL }

The second field is the value field and this is checked in revision
2.1.17 in ldap_sasl_bind() but not checked in rev 2.1.16.

The other change is to replace the ldap objectclass to use the newer
OpenLDAP class (Check comments).


Tanks to Luke Howard for writing the hdb-ldap interfase and Howard Chu
for the changes to support the new authentication restrictions in
OpenLDAP 2.1.x.

This is the small patch:
I used diff -Naur heimdal-0.5.2/lib/hdb/hdb-ldap.c
heimdal/lib/hdb/hdb-ldap.c


--- heimdal-0.5.2/lib/hdb/hdb-ldap.c	2002-09-04 13:42:22.000000000 -0500
+++ heimdal/lib/hdb/hdb-ldap.c	2003-05-08 20:01:22.000000000 -0500
@@ -32,7 +32,7 @@
 
 #include "hdb_locl.h"
 
-RCSID("$Id: hdb-ldap.c,v 1.10 2002/09/04 18:42:22 joda Exp $");
+RCSID("$Id: hdb-ldap.c,v 1.2 2003/01/21 18:58:28 albertop Exp $");
 
 #ifdef OPENLDAP
 
@@ -298,8 +298,16 @@
 	if (ret != 0) {
 	    goto out;
 	}
-	/* person is the structural object class */
-	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "person");
+	/* person is the old structural object class */
+	/* From the OpenLDAP FAQ-O-Matic: A common error that is encountered when    */
+	/* upgrading from earlier versions of OpenLDAP is 'invalid structural object */
+	/* class chain'. This occurs because 2.1.x versions enforce more of the LDAP */
+	/* structure rules than 2.0.x did, and many directories contain incorrect    */
+	/* data because of the lax checking of the earlier versions.                 */ 
+	
+	/* So we could avoid this problem using the OpenLDAPperson objectclass       */
+	/* instead of the person object class */
+	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "OpenLDAPperson" );
 	if (ret != 0) {
 	    goto out;
 	}
@@ -953,6 +961,7 @@
 static krb5_error_code LDAP__connect(krb5_context context, HDB * db)
 {
     int rc, version = LDAP_VERSION3;
+    struct berval bv = {0, ""};
 
     if (db->db != NULL) {
 	/* connection has been opened. ping server. */
@@ -986,6 +995,14 @@
 	return HDB_ERR_BADVERSION;
     }
 
+    rc = ldap_sasl_bind_s((LDAP *) db->db, NULL, "EXTERNAL", &bv, NULL, NULL, NULL );
+    if (rc != LDAP_SUCCESS) {
+	krb5_set_error_string(context, "ldap_sasl_bind_s: %s", ldap_err2string(rc));
+	ldap_unbind_ext((LDAP *) db->db, NULL, NULL);
+	db->db = NULL;
+	return HDB_ERR_BADVERSION;
+    }
+
     return 0;
 }
 
@@ -1051,6 +1068,8 @@
     int rc;
     LDAPMessage *msg = NULL, *e = NULL;
     char *dn = NULL, *name = NULL;
+    /* Required by the OpenLDAP objectclass */
+    char *userid = NULL;
 
     ret = krb5_unparse_name(context, entry->principal, &name);
     if (ret != 0) {
@@ -1099,12 +1118,22 @@
 	if (ret < 0) {
 	    goto out;
 	}
+	
+	/* userid is a new field required by the OpenLDAPperson objectclass */
+	userid = strdup(name);
+	/* Remove REALM from userid */
+	p = strchr(userid,'@');
+	*p = '\0';
+	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "userid", userid);
+	if (ret < 0) {
+	    goto out;
+	}
 
 	if (db->name != NULL) {
 	    ret = asprintf(&dn, "cn=%s,%s", name, db->name);
 	} else {
 	    /* A bit bogus, but we don't have a search base */
-	    ret = asprintf(&dn, "cn=%s", name, db->name);
+	    ret = asprintf(&dn, "cn=%s", name);
 	}
 	if (ret < 0) {
 	    krb5_set_error_string(context, "asprintf: out of memory");
@@ -1156,6 +1185,9 @@
 	free(name);
     }
 
+    if (userid != NULL) {
+	free(userid);
+    }
     return ret;
 }