]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
don't return entry if requested attr is not present (ITS#5650)
[openldap] / servers / slapd / syncrepl.c
index f4981f32e6ef53f6ae3e7494ce07227c4982b45c..4378ee9383d7880e95108fbb13a01329d1c40af3 100644 (file)
@@ -579,11 +579,14 @@ do_syncrep1(
 
        ldap_set_option( si->si_ld, LDAP_OPT_TIMELIMIT, &si->si_tlimit );
 
+       rc = LDAP_DEREF_NEVER;  /* actually could allow DEREF_FINDING */
+       ldap_set_option( si->si_ld, LDAP_OPT_DEREF, &rc );
+
        si->si_syncCookie.rid = si->si_rid;
 
        /* whenever there are multiple data sources possible, advertise sid */
-       si->si_syncCookie.sid = ( SLAP_MULTIMASTER( si->si_be ) || SLAP_GLUE_SUBORDINATE( si->si_be ) ||
-               SLAP_GLUE_INSTANCE( si->si_be )) ? slap_serverID : -1;
+       si->si_syncCookie.sid = ( SLAP_MULTIMASTER( si->si_be ) || si->si_be != si->si_wbe ) ?
+               slap_serverID : -1;
 
        /* We've just started up, or the remote server hasn't sent us
         * any meaningful state.
@@ -689,8 +692,8 @@ compare_csns( struct sync_cookie *sc1, struct sync_cookie *sc2, int *which )
                return -1;
        }
 
-       for (i=0; i<sc1->numcsns; i++) {
-               for (j=0; j<sc2->numcsns; j++) {
+       for (j=0; j<sc2->numcsns; j++) {
+               for (i=0; i<sc1->numcsns; i++) {
                        if ( sc1->sids[i] != sc2->sids[j] )
                                continue;
                        value_match( &match, slap_schema.si_ad_entryCSN,
@@ -703,6 +706,11 @@ compare_csns( struct sync_cookie *sc1, struct sync_cookie *sc2, int *which )
                        }
                        break;
                }
+               if ( i == sc1->numcsns ) {
+                       /* sc2 has a sid sc1 lacks */
+                       *which = j;
+                       return -1;
+               }
        }
        return match;
 }
@@ -906,6 +914,11 @@ do_syncrep2(
                                rc = err;
                                goto done;
                        }
+                       if ( err ) {
+                               Debug( LDAP_DEBUG_ANY,
+                                       "do_syncrep2: %s LDAP_RES_SEARCH_RESULT (%d) %s\n",
+                                       si->si_ridtxt, err, ldap_err2string( err ) );
+                       }
                        if ( rctrls ) {
                                rctrlp = *rctrls;
                                ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
@@ -1242,7 +1255,8 @@ do_syncrepl(
         *
         * Typically there is a single syncprov mastering the entire
         * glued tree. In that case, our contextCSN updates should
-        * go to the master DB.
+        * go to the master DB. But if there is no syncprov on the
+        * master DB, then nothing special is needed here.
         *
         * Alternatively, there may be individual syncprov overlays
         * on each glued branch. In that case, each syncprov only
@@ -1251,7 +1265,11 @@ do_syncrepl(
         */
        if ( !si->si_wbe ) {
                if ( SLAP_GLUE_SUBORDINATE( be ) && !overlay_is_inst( be, "syncprov" )) {
-                       si->si_wbe = select_backend( &be->be_nsuffix[0], 1 );
+                       BackendDB * top_be = select_backend( &be->be_nsuffix[0], 1 );
+                       if ( overlay_is_inst( top_be, "syncprov" ))
+                               si->si_wbe = select_backend( &be->be_nsuffix[0], 1 );
+                       else
+                               si->si_wbe = be;
                } else {
                        si->si_wbe = be;
                }
@@ -2728,6 +2746,7 @@ syncrepl_updateCookie(
        mod.sml_op = LDAP_MOD_REPLACE;
        mod.sml_desc = slap_schema.si_ad_contextCSN;
        mod.sml_type = mod.sml_desc->ad_cname;
+       mod.sml_flags = SLAP_MOD_INTERNAL;
        mod.sml_nvalues = NULL;
        mod.sml_next = NULL;
 
@@ -2872,6 +2891,14 @@ attr_cmp( Operation *op, Attribute *old, Attribute *new,
                        }
                }
 
+               /* Don't delete/add an objectClass, always use the replace op.
+                * Modify would fail if provider has replaced entry with a new,
+                * and the new explicitly includes a superior of a class that was
+                * only included implicitly in the old entry.  Ref ITS#5517.
+                */
+               if ( nn && no < o && old->a_desc == slap_schema.si_ad_objectClass )
+                       no = o;
+
                i = j;
                /* all old values were deleted, just use the replace op */
                if ( no == o ) {