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)) {

Reply via email to