Cannot Change OpenLDAP Password in Lion System Preferences

Originator:MichaelJSmalley
Number:rdar://11768796 Date Originated:28-Jun-2012 11:34 AM
Status:Open Resolved:
Product:Mac OS X Product Version:10.7.4
Classification:Security Reproducible:Yes
 
Summary:
Users are unable to change their password using System Preferences -> Users & Groups on a Mac that is connected to an LDAP server (specifically, OpenLDAP).

This error appears to be a result of OS X 10.7.4 now sending the username of the user rather than their full DN (e.g. it's sending 'bobsmith', not 'uid=bobsmith,ou=Users,dc=companyname,dc=com')

Steps to Reproduce:
Try to change the password using the System Preferences -> Users & Groups prefpane on Lion. It fails with the following error message:

The password for the account “<bobsmith>” was not changed.

Your system administrator may not allow you to change your password or there was some other problem with your password. Contact your system administrator for help.

Expected Results:
The password should be changed.

Actual Results:
The error appears, and on the LDAP server, an error like the following is logged:

Jun 28 08:42:21 ldap3 slapd[7810]: conn=10518785 op=2 RESULT oid= err=21 text=Invalid DN

This error appears to be a result of OS X 10.7.4 now sending the username of the user rather than their full DN (e.g. it's sending 'bobsmith', not 'uid=bobsmith,ou=Users,dc=companyname,dc=com')

Regression:

Notes:
This was encountered by someone else who ended up patching their LDAP server to resolve the issue. This shouldn't require patching LDAP to resolve, however. Lion needs to (at least have an option to) send the full DN, not the short username:

http://afp548.com/forums/topic/openldap-lion-password-changes-via-system-preferences/

Text from above link (in case it is taken down):
"So, I’ve got this OpenLDAP server with network home directories at home that all of my Mac machines authenticate to. Everybody can bounce around to whatever Mac is available. It works great.  

Anyway, with Snow Leopard, I was able to change user passwords via System Preferences. However, that got broken when I upgraded to Lion (amongst other things). Both Snow Leopard and Lion send exop’s to the ldap server, but for whatever reason, the id is screwed up in Lion (or at least, it’s screwed up on the two machines at home I tested this with). Instead of sending the user’s DN, e.g. “uid=user,cn=users,ou=something,dc=somewhere,dc=com”, the ldap server is only sent the uid, e.g. “user”. The ldap server is expecting a DN here, so naturally, it fails with the error “Invalid DN”.

Bummer.

So, to work around that, I had to patch OpenLDAP (version 2.4.26 in this case). Now, when my server can’t resolve the id it’s given during a password change, it will look at the bind DN, and if the id string is contained within the bind DN string, it will just use the bind DN as the entry to change. I figured this would still allow me to manually specify password changes via an admin account while still giving users the ability to change their own passwords without having to point them at a webpage (lame).

I should point out that all my accounts have the uid as part of the DN… I guess if you were doing some kind of crazy SASL mappings, this might not work for you…

Anyway, here’s the patch in case anyone else is interested… If it works for you, great. If not, oh well.

-- passwd.c	2011-06-30 11:13:36.000000000 -0400
+++ passwd.lion_compatability.c	2012-02-13 22:48:54.213214617 -0500
@@ -18,4 +18,5 @@

 #include <stdio.h>
+#include <string.h>

 #include <ac/socket.h>
@@ -59,4 +60,5 @@
 	int freenewpw = 0;
 	struct berval dn = BER_BVNULL, ndn = BER_BVNULL;
+	ber_int_t err;

 	assert( ber_bvcmp( &slap_EXOP_MODIFY_PASSWD, &op->ore_reqoid ) == 0 );
@@ -102,11 +104,8 @@

 	if ( !BER_BVISEMPTY( &id ) ) {
-		rs->sr_err = dnPrettyNormal( NULL, &id, &dn, &ndn, op->o_tmpmemctx );
-		id.bv_val[id.bv_len] = idNul;
-		if ( rs->sr_err != LDAP_SUCCESS ) {
-			rs->sr_text = "Invalid DN";
-			rc = rs->sr_err;
-			goto error_return;
-		}
+		err = dnPrettyNormal( NULL, &id, &dn, &ndn, op->o_tmpmemctx );
+	}
+
+	if ( !BER_BVISEMPTY( &id ) && (err == LDAP_SUCCESS) ) {
 		op->o_req_dn = dn;
 		op->o_req_ndn = ndn;
@@ -116,4 +115,16 @@
 		ber_dupbv_x( &dn, &op->o_dn, op->o_tmpmemctx );
 		ber_dupbv_x( &ndn, &op->o_ndn, op->o_tmpmemctx );
+		if ( !BER_BVISEMPTY( &id ) ) {
+			/* See if the id matches the bind dn */
+			if ( strstr( dn.bv_val, id.bv_val ) == NULL )
+			{
+				rs->sr_err = err; /* From dnPrettyNormal */
+				rs->sr_text = "Invalid DN";
+				rc = rs->sr_err;
+				goto error_return;
+			}
+			Statslog( LDAP_DEBUG_STATS, "%s Invalid id (%s) specified; using bind DN (%s)\n",
+					op->o_log_prefix, id.bv_val, dn.bv_val, 0, 0 );
+		}
 		op->o_req_dn = dn;
 		op->o_req_ndn = ndn;
@@ -123,4 +134,8 @@
 	}

+	if ( !BER_BVISEMPTY( &id ) ) {
+		id.bv_val[id.bv_len] = idNul;
+	}
+
 	if( op->o_bd == NULL ) {
 		if ( qpw->rs_old.bv_val != NULL ) {
"

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!