HEAD pdb_ldap

Volker Lendecke Volker.Lendecke at SerNet.DE
Thu Mar 20 23:03:37 GMT 2003


Hi!

The attached patch changes some semantics in pdb_get_set.

I had the problem that I could not join a HEAD PDC with NT4. HEAD
tried to do illegal operations with the LDAP account, for example it
tried to set "displayName" to "", which is not allowed. I found we
have to track what attributes exist in LDAP to make the appropriate
change.

See the function make_ldap_mod for the core functionality.

To enable that, the semantics of IS_SAM_SET changed to: Did this exist
in LDAP? and IS_SAM_CHANGED means: Do we have to set it?

Not really tested what this semantic change breaks, but with that
patch I can now join HEAD with ldapsam again.

Comments?

BTW, this also does away with the 'cn' and 'displayName'
co-treatment. This is simply not possible.

Volker

Not signed, gpg would destroy the diff ;-)

Index: include/smb.h
===================================================================
RCS file: /space/vl/cvstree/samba/source/include/smb.h,v
retrieving revision 1.479
diff -u -r1.479 smb.h
--- include/smb.h	20 Mar 2003 00:32:44 -0000	1.479
+++ include/smb.h	20 Mar 2003 22:53:35 -0000
@@ -628,8 +628,6 @@
 	(( pdb_get_init_flags(x, PDB_UID) != PDB_DEFAULT ) \
 	 && ( pdb_get_init_flags(x,PDB_GID) != PDB_DEFAULT ))
 
-#define IS_SAM_SET(x, flag)	(pdb_get_init_flags(x, flag) == PDB_SET)
-#define IS_SAM_CHANGED(x, flag)	(pdb_get_init_flags(x, flag) == PDB_CHANGED)
 #define IS_SAM_DEFAULT(x, flag)	(pdb_get_init_flags(x, flag) == PDB_DEFAULT)
 		
 typedef struct sam_passwd
Index: passdb/passdb.c
===================================================================
RCS file: /space/vl/cvstree/samba/source/passdb/passdb.c,v
retrieving revision 1.187
diff -u -r1.187 passdb.c
--- passdb/passdb.c	22 Feb 2003 12:17:02 -0000	1.187
+++ passdb/passdb.c	20 Mar 2003 22:54:10 -0000
@@ -863,7 +863,8 @@
 	
 	if (pdb_getsampwsid(sam_user, psid)) {
 		
-		if (!IS_SAM_SET(sam_user,PDB_UID)&&!IS_SAM_CHANGED(sam_user,PDB_UID)) {
+		if (!pdb_is_sam_set(sam_user,PDB_UID)&&
+		    !pdb_is_sam_changed(sam_user,PDB_UID)) {
 			pdb_free_sam(&sam_user);
 			return False;
 		}
Index: passdb/pdb_get_set.c
===================================================================
RCS file: /space/vl/cvstree/samba/source/passdb/pdb_get_set.c,v
retrieving revision 1.23
diff -u -r1.23 pdb_get_set.c
--- passdb/pdb_get_set.c	20 Mar 2003 12:50:29 -0000	1.23
+++ passdb/pdb_get_set.c	20 Mar 2003 22:55:12 -0000
@@ -202,6 +202,22 @@
         return ret;
 }
 
+BOOL pdb_is_sam_set(const SAM_ACCOUNT *sampass, enum pdb_elements element)
+{
+	if (!sampass || !sampass->private.set_flags)
+		return False;
+
+	return bitmap_query(sampass->private.set_flags, element);
+}
+
+BOOL pdb_is_sam_changed(const SAM_ACCOUNT *sampass, enum pdb_elements element)
+{
+	if (!sampass || !sampass->private.change_flags)
+		return False;
+
+	return bitmap_query(sampass->private.change_flags, element);
+}
+
 uid_t pdb_get_uid (const SAM_ACCOUNT *sampass)
 {
 	if (sampass)
@@ -475,17 +491,9 @@
 				DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
 				return False;
 			}
-        		if (!bitmap_set(sampass->private.set_flags, element)) {
-				DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
-				return False;
-			}
 			DEBUG(11, ("element %d -> now CHANGED\n", element)); 
         		break;
         	case PDB_SET:
-        		if (!bitmap_clear(sampass->private.change_flags, element)) {
-				DEBUG(0,("Can't set flag: %d in change_flags.\n",element));
-				return False;
-			}
         		if (!bitmap_set(sampass->private.set_flags, element)) {
 				DEBUG(0,("Can't set flag: %d in set_flags.\n",element));
 				return False;
Index: passdb/pdb_ldap.c
===================================================================
RCS file: /space/vl/cvstree/samba/source/passdb/pdb_ldap.c,v
retrieving revision 1.88
diff -u -r1.88 pdb_ldap.c
--- passdb/pdb_ldap.c	20 Mar 2003 13:21:23 -0000	1.88
+++ passdb/pdb_ldap.c	20 Mar 2003 22:50:33 -0000
@@ -1158,12 +1158,8 @@
 	 * that fits your needs; using cn then displayName rather than 'userFullName'
 	 */
 
-	if (!get_single_attribute(ldap_state->ldap_struct, entry, "cn", fullname)) {
-		if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName", fullname)) {
-			/* leave as default */
-		} else {
-			pdb_set_fullname(sampass, fullname, PDB_SET);
-		}
+	if (!get_single_attribute(ldap_state->ldap_struct, entry, "displayName", fullname)) {
+		/* leave as default */
 	} else {
 		pdb_set_fullname(sampass, fullname, PDB_SET);
 	}
@@ -1275,7 +1271,27 @@
 	if (pdb_add) {
 		return (!IS_SAM_DEFAULT(sampass, element));
 	} else {
-		return IS_SAM_CHANGED(sampass, element);
+		return pdb_is_sam_changed(sampass, element);
+	}
+}
+
+static void make_ldap_mod(LDAPMod ***mods, const SAM_ACCOUNT *sampass,
+			  enum pdb_elements element,
+			  const char *attrib, const char *newval)
+{
+	if (!pdb_is_sam_changed(sampass, element))
+		return;
+	
+	if (pdb_is_sam_set(sampass, element)) {
+		if (strlen(newval) > 0) {
+			make_a_mod(mods, LDAP_MOD_REPLACE, attrib, newval);
+		} else {
+			make_a_mod(mods, LDAP_MOD_DELETE, attrib, NULL);
+		}
+	} else {
+		if (strlen(newval) > 0) {
+			make_a_mod(mods, LDAP_MOD_ADD, attrib, newval);
+		}
 	}
 }
 
@@ -1349,66 +1365,61 @@
 		return False;
 	}
 
+	make_ldap_mod(mods, sampass,
+		      PDB_FULLNAME, "displayName",
+		      pdb_get_fullname(sampass));
+
+	make_ldap_mod(mods, sampass,
+		      PDB_ACCTDESC, "description",
+		      pdb_get_acct_desc(sampass));
+
+	make_ldap_mod(mods, sampass,
+		      PDB_WORKSTATIONS, "userWorkstations",
+		      pdb_get_workstations(sampass));
+
+	make_ldap_mod(mods, sampass,
+		      PDB_SMBHOME, "smbHome",
+		      pdb_get_homedir(sampass));
+
+	make_ldap_mod(mods, sampass,
+		      PDB_DRIVE, "homeDrive",
+		      pdb_get_dir_drive(sampass));
+
+	make_ldap_mod(mods, sampass,
+		      PDB_LOGONSCRIPT, "scriptPath",
+		      pdb_get_logon_script(sampass));
+
+	make_ldap_mod(mods, sampass,
+		      PDB_PROFILE, "profilePath",
+		      pdb_get_profile_path(sampass));
+
+	slprintf(temp, sizeof(temp)-1, "%li", pdb_get_logon_time(sampass));
+	make_ldap_mod(mods, sampass,
+		      PDB_LOGONTIME, "logonTime",
+		      temp);
+
+	slprintf(temp, sizeof(temp)-1, "%li", pdb_get_logoff_time(sampass));
+	make_ldap_mod(mods, sampass,
+		      PDB_LOGOFFTIME, "logoffTime",
+		      temp);
 
-	/* displayName, cn, and gecos should all be the same
-	 *  most easily accomplished by giving them the same OID
-	 *  gecos isn't set here b/c it should be handled by the 
-	 *  add-user script
-	 */
-	if (need_ldap_mod(pdb_add, sampass, PDB_FULLNAME)) {
-		make_a_mod(mods, ldap_op, "displayName", pdb_get_fullname(sampass));
-		make_a_mod(mods, ldap_op, "cn", pdb_get_fullname(sampass));
-	}
-	if (need_ldap_mod(pdb_add, sampass, PDB_ACCTDESC)) {	
-		make_a_mod(mods, ldap_op, "description", pdb_get_acct_desc(sampass));
-	}
-	if (need_ldap_mod(pdb_add, sampass, PDB_WORKSTATIONS)) {	
-		make_a_mod(mods, ldap_op, "userWorkstations", pdb_get_workstations(sampass));
-	}
-	/*
-	 * Only updates fields which have been set (not defaults from smb.conf)
-	 */
-
-	if (need_ldap_mod(pdb_add, sampass, PDB_SMBHOME)) {
-		make_a_mod(mods, ldap_op, "smbHome", pdb_get_homedir(sampass));
-	}
-			
-	if (need_ldap_mod(pdb_add, sampass, PDB_DRIVE)) {
-		make_a_mod(mods, ldap_op, "homeDrive", pdb_get_dir_drive(sampass));
-	}
-	
-	if (need_ldap_mod(pdb_add, sampass, PDB_LOGONSCRIPT)) {
-		make_a_mod(mods, ldap_op, "scriptPath", pdb_get_logon_script(sampass));
-	}
 	
-	if (need_ldap_mod(pdb_add, sampass, PDB_PROFILE))
-		make_a_mod(mods, ldap_op, "profilePath", pdb_get_profile_path(sampass));
-
-	if (need_ldap_mod(pdb_add, sampass, PDB_LOGONTIME)) {
-		slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass));
-		make_a_mod(mods, ldap_op, "logonTime", temp);
-	}
-
-	if (need_ldap_mod(pdb_add, sampass, PDB_LOGOFFTIME)) {
-		slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
-		make_a_mod(mods, ldap_op, "logoffTime", temp);
-	}
-
-	if (need_ldap_mod(pdb_add, sampass, PDB_KICKOFFTIME)) {
-		slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass));
-		make_a_mod(mods, ldap_op, "kickoffTime", temp);
-	}
-
-
-	if (need_ldap_mod(pdb_add, sampass, PDB_CANCHANGETIME)) {
-		slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
-		make_a_mod(mods, ldap_op, "pwdCanChange", temp);
-	}
-
-	if (need_ldap_mod(pdb_add, sampass, PDB_MUSTCHANGETIME)) {
-		slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass));
-		make_a_mod(mods, ldap_op, "pwdMustChange", temp);
-	}
+	slprintf (temp, sizeof (temp)-1, "%li", pdb_get_kickoff_time(sampass));
+	make_ldap_mod(mods, sampass,
+		      PDB_KICKOFFTIME, "kickoffTime",
+		      temp);
+
+	slprintf (temp, sizeof (temp)-1, "%li",
+		  pdb_get_pass_can_change_time(sampass));
+	make_ldap_mod(mods, sampass,
+		      PDB_CANCHANGETIME, "pwdCanChange",
+		      temp);
+
+	slprintf (temp, sizeof (temp)-1, "%li",
+		  pdb_get_pass_must_change_time(sampass));
+	make_ldap_mod(mods, sampass,
+		      PDB_MUSTCHANGETIME, "pwdMustChange",
+		      temp);
 
 	if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
 		(lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {



More information about the samba-technical mailing list