]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#9227 syncrepl: don't delete non-replicated attrs
authorHoward Chu <hyc@openldap.org>
Fri, 8 May 2020 15:22:44 +0000 (16:22 +0100)
committerQuanah Gibson-Mount <quanah@openldap.org>
Mon, 11 May 2020 21:45:44 +0000 (21:45 +0000)
servers/slapd/syncrepl.c

index e968e7b09aad0f02648aaaaf3715f8adab069c78..c659a32752a8717840682179e3c27bb580990b95 100644 (file)
@@ -2788,6 +2788,7 @@ static struct berval generic_filterstr = BER_BVC("(objectclass=*)");
  * operational attributes from the entry, and do a regular ModDN.
  */
 typedef struct dninfo {
+       syncinfo_t *si;
        Entry *new_entry;
        struct berval dn;
        struct berval ndn;
@@ -3010,6 +3011,7 @@ syncrepl_entry(
        op->o_callback = &cb;
        cb.sc_response = dn_callback;
        cb.sc_private = &dni;
+       dni.si = si;
        dni.new_entry = entry;
        dni.modlist = modlist;
 
@@ -4292,6 +4294,37 @@ void syncrepl_diff_entry( Operation *op, Attribute *old, Attribute *new,
        *ml = NULL;
 }
 
+/* shallow copy attrs, excluding non-replicated attrs */
+static Attribute *
+attrs_exdup( Operation *op, dninfo *dni, Attribute *attrs )
+{
+       int i;
+       Attribute *tmp, *anew;
+
+       if ( attrs == NULL ) return NULL;
+
+       /* count attrs */
+       for ( tmp = attrs,i=0; tmp; tmp=tmp->a_next ) i++;
+
+       anew = op->o_tmpalloc( i * sizeof(Attribute), op->o_tmpmemctx );
+       for ( tmp = anew; attrs; attrs=attrs->a_next ) {
+               if ( dni->si->si_anlist && !ad_inlist( attrs->a_desc, dni->si->si_anlist ))
+                       continue;
+               if ( dni->si->si_exanlist && ad_inlist( attrs->a_desc, dni->si->si_exanlist ))
+                       continue;
+               *tmp = *attrs;
+               tmp->a_next = tmp+1;
+               tmp++;
+       }
+       if ( tmp == anew ) {
+               /* excluded everything */
+               op->o_tmpfree( anew, op->o_tmpmemctx );
+               return NULL;
+       }
+       tmp[-1].a_next = NULL;
+       return anew;
+}
+
 static int
 dn_callback(
        Operation*      op,
@@ -4414,9 +4447,13 @@ dn_callback(
                                         */
                                }
 
-                               syncrepl_diff_entry( op, rs->sr_entry->e_attrs,
-                                       dni->new_entry->e_attrs, &dni->mods, dni->modlist,
-                                       is_ctx );
+                               {
+                                       Attribute *old = attrs_exdup( op, dni, rs->sr_entry->e_attrs );
+                                       syncrepl_diff_entry( op, old,
+                                               dni->new_entry->e_attrs, &dni->mods, dni->modlist,
+                                               is_ctx );
+                                       op->o_tmpfree( old, op->o_tmpmemctx );
+                               }
                        }
                }
        } else if ( rs->sr_type == REP_RESULT ) {