]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/syncrepl.c
- setup framework for monitoring of back-bdb/back-hdb stuff in their
[openldap] / servers / slapd / syncrepl.c
index b166e014ac0ed2538a9e5b8412838a8cc8fd2341..a92e59225b953c84de4ce2c5ccec9c2728f3635e 100644 (file)
@@ -83,9 +83,6 @@ typedef struct syncinfo_s {
        int                                     si_syncdata;
        int                                     si_logstate;
        int                                     si_conn_setup;
-#ifdef HAVE_TLS
-       int                                     si_check_tls;
-#endif
        Avlnode                         *si_presentlist;
        LDAP                            *si_ld;
        LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
@@ -94,7 +91,7 @@ typedef struct syncinfo_s {
 
 static int syncuuid_cmp( const void *, const void * );
 static void avl_ber_bvfree( void * );
-static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray );
+static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray, struct berval * );
 static int syncrepl_message_to_op(
                                        syncinfo_t *, Operation *, LDAPMessage * );
 static int syncrepl_message_to_entry(
@@ -426,118 +423,11 @@ do_syncrep1(
 
        psub = &si->si_be->be_nsuffix[0];
 
-       /* Init connection to master */
-       rc = ldap_initialize( &si->si_ld, si->si_bindconf.sb_uri.bv_val );
+       rc = slap_client_connect( &si->si_ld, &si->si_bindconf, LDAP_VERSION3 );
        if ( rc != LDAP_SUCCESS ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_syncrep1: ldap_initialize failed (%s)\n",
-                       si->si_bindconf.sb_uri.bv_val, 0, 0 );
-               return rc;
-       }
-
-       op->o_protocol = LDAP_VERSION3;
-       ldap_set_option( si->si_ld, LDAP_OPT_PROTOCOL_VERSION, &op->o_protocol );
-
-#ifdef HAVE_TLS
-       if ( si->si_check_tls ) {
-               si->si_check_tls = 0;
-               rc = bindconf_tls_set( &si->si_bindconf, si->si_ld );
-       } else if ( si->si_bindconf.sb_tls_ctx ) {
-               rc = ldap_set_option( si->si_ld, LDAP_OPT_X_TLS_CTX,
-                       si->si_bindconf.sb_tls_ctx );
-       }
-       if ( rc ) {
-               Debug( LDAP_DEBUG_ANY,
-                       "do_syncrep1: TLS context initialization failed\n", 0, 0, 0 );
-               return rc;
-       }
-#endif
-
-       /* Bind to master */
-
-       if ( si->si_bindconf.sb_tls ) {
-               rc = ldap_start_tls_s( si->si_ld, NULL, NULL );
-               if( rc != LDAP_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY,
-                               "%s: ldap_start_tls failed (%d)\n",
-                               si->si_bindconf.sb_tls == SB_TLS_CRITICAL ? "Error" : "Warning",
-                               rc, 0 );
-                       if( si->si_bindconf.sb_tls == SB_TLS_CRITICAL ) goto done;
-               }
-       }
-
-       if ( si->si_bindconf.sb_method == LDAP_AUTH_SASL ) {
-#ifdef HAVE_CYRUS_SASL
-               void *defaults;
-
-               if ( si->si_bindconf.sb_secprops != NULL ) {
-                       rc = ldap_set_option( si->si_ld,
-                               LDAP_OPT_X_SASL_SECPROPS, si->si_bindconf.sb_secprops);
-
-                       if( rc != LDAP_OPT_SUCCESS ) {
-                               Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
-                                       "(%s,SECPROPS,\"%s\") failed!\n",
-                                       si->si_bindconf.sb_uri.bv_val, si->si_bindconf.sb_secprops, 0 );
-                               goto done;
-                       }
-               }
-
-               defaults = lutil_sasl_defaults( si->si_ld,
-                       si->si_bindconf.sb_saslmech.bv_val,
-                       si->si_bindconf.sb_realm.bv_val,
-                       si->si_bindconf.sb_authcId.bv_val,
-                       si->si_bindconf.sb_cred.bv_val,
-                       si->si_bindconf.sb_authzId.bv_val );
-
-               rc = ldap_sasl_interactive_bind_s( si->si_ld,
-                               si->si_bindconf.sb_binddn.bv_val,
-                               si->si_bindconf.sb_saslmech.bv_val,
-                               NULL, NULL,
-                               LDAP_SASL_QUIET,
-                               lutil_sasl_interact,
-                               defaults );
-
-               lutil_sasl_freedefs( defaults );
-
-               /* FIXME: different error behaviors according to
-                *      1) return code
-                *      2) on err policy : exit, retry, backoff ...
-                */
-               if ( rc != LDAP_SUCCESS ) {
-                       static struct berval bv_GSSAPI = BER_BVC( "GSSAPI" );
-
-                       Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
-                               "ldap_sasl_interactive_bind_s failed (%d)\n",
-                               rc, 0, 0 );
-
-                       /* FIXME (see above comment) */
-                       /* if Kerberos credentials cache is not active, retry */
-                       if ( ber_bvcmp( &si->si_bindconf.sb_saslmech, &bv_GSSAPI ) == 0 &&
-                               rc == LDAP_LOCAL_ERROR )
-                       {
-                               rc = LDAP_SERVER_DOWN;
-                       }
-
-                       goto done;
-               }
-#else /* HAVE_CYRUS_SASL */
-               /* Should never get here, we trapped this at config time */
-               assert(0);
-               Debug( LDAP_DEBUG_SYNC, "not compiled with SASL support\n", 0, 0, 0 );
-               rc = LDAP_OTHER;
                goto done;
-#endif
-
-       } else if ( si->si_bindconf.sb_method == LDAP_AUTH_SIMPLE ) {
-               rc = ldap_sasl_bind_s( si->si_ld,
-                       si->si_bindconf.sb_binddn.bv_val, LDAP_SASL_SIMPLE,
-                       &si->si_bindconf.sb_cred, NULL, NULL, NULL );
-               if ( rc != LDAP_SUCCESS ) {
-                       Debug( LDAP_DEBUG_ANY, "do_syncrep1: "
-                               "ldap_sasl_bind_s failed (%d)\n", rc, 0, 0 );
-                       goto done;
-               }
        }
+       op->o_protocol = LDAP_VERSION3;
 
        /* Set SSF to strongest of TLS, SASL SSFs */
        op->o_sasl_ssf = 0;
@@ -811,11 +701,6 @@ do_syncrep2(
                                                &syncCookie_req.ctxcsn, &syncCookie.ctxcsn,
                                                &text );
                                }
-                               if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
-                                       match < 0 && err == LDAP_SUCCESS )
-                               {
-                                       rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
-                               }
                                if ( rctrls ) {
                                        ldap_controls_free( rctrls );
                                }
@@ -827,12 +712,17 @@ do_syncrep2(
                                        if ( refreshDeletes == 0 && match < 0 &&
                                                err == LDAP_SUCCESS )
                                        {
-                                               syncrepl_del_nonpresent( op, si, NULL );
+                                               syncrepl_del_nonpresent( op, si, NULL, &syncCookie.ctxcsn );
                                        } else {
                                                avl_free( si->si_presentlist, avl_ber_bvfree );
                                                si->si_presentlist = NULL;
                                        }
                                }
+                               if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
+                                       match < 0 && err == LDAP_SUCCESS )
+                               {
+                                       rc = syncrepl_updateCookie( si, op, psub, &syncCookie );
+                               }
                                if ( err == LDAP_SUCCESS
                                        && si->si_logstate == SYNCLOG_FALLBACK ) {
                                        si->si_logstate = SYNCLOG_LOGGING;
@@ -919,7 +809,8 @@ do_syncrep2(
                                                ber_scanf( ber, "[W]", &syncUUIDs );
                                                ber_scanf( ber, /*"{"*/ "}" );
                                                if ( refreshDeletes ) {
-                                                       syncrepl_del_nonpresent( op, si, syncUUIDs );
+                                                       syncrepl_del_nonpresent( op, si, syncUUIDs,
+                                                               &syncCookie.ctxcsn );
                                                        ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx );
                                                } else {
                                                        for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) {
@@ -932,6 +823,7 @@ do_syncrep2(
                                                        }
                                                        slap_sl_free( syncUUIDs, op->o_tmpmemctx );
                                                }
+                                               slap_sync_cookie_free( &syncCookie, 0 );
                                                break;
                                        default:
                                                Debug( LDAP_DEBUG_ANY,
@@ -954,15 +846,14 @@ do_syncrep2(
                                                        &syncCookie.ctxcsn, &text );
                                        }
 
-                                       if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
-                                               match < 0 )
-                                       {
-                                               rc = syncrepl_updateCookie( si, op, psub, &syncCookie);
-                                       }
+                                       if ( match < 0 ) {
+                                               if ( si->si_refreshPresent == 1 ) {
+                                                       syncrepl_del_nonpresent( op, si, NULL, &syncCookie.ctxcsn );
+                                               }
 
-                                       if ( si->si_refreshPresent == 1 ) {
-                                               if ( match < 0 ) {
-                                                       syncrepl_del_nonpresent( op, si, NULL );
+                                               if ( !BER_BVISNULL( &syncCookie.ctxcsn ))
+                                               {
+                                                       rc = syncrepl_updateCookie( si, op, psub, &syncCookie);
                                                }
                                        } 
 
@@ -1352,6 +1243,7 @@ syncrepl_message_to_op(
        }
 
        op->o_callback = &cb;
+       slap_op_time( &op->o_time, &op->o_tincr );
 
        switch( op->o_tag ) {
        case LDAP_REQ_ADD:
@@ -1368,7 +1260,7 @@ syncrepl_message_to_op(
                }
 
                if ( op->o_tag == LDAP_REQ_ADD ) {
-                       op->ora_e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
+                       op->ora_e = entry_alloc();
                        op->ora_e->e_name = op->o_req_dn;
                        op->ora_e->e_nname = op->o_req_ndn;
                        rc = slap_mods2entry( modlist, &op->ora_e, 1, 0, &text, txtbuf, textlen);
@@ -1497,7 +1389,7 @@ syncrepl_message_to_entry(
                return -1;
        }
 
-       e = ( Entry * ) ch_calloc( 1, sizeof( Entry ) );
+       e = entry_alloc();
        e->e_name = op->o_req_dn;
        e->e_nname = op->o_req_ndn;
 
@@ -1690,8 +1582,13 @@ syncrepl_entry(
        f.f_choice = LDAP_FILTER_EQUALITY;
        f.f_ava = &ava;
        ava.aa_desc = slap_schema.si_ad_entryUUID;
-       (void)slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
        ava.aa_value = *syncUUID;
+
+       (void)slap_uuidstr_from_normalized( &syncUUID_strrep, syncUUID, op->o_tmpmemctx );
+       if ( syncuuid_bv ) {
+               Debug( LDAP_DEBUG_SYNC, "syncrepl_entry: inserted UUID %s\n",
+                       syncUUID_strrep.bv_val, 0, 0 );
+       }
        op->ors_filter = &f;
 
        op->ors_filterstr.bv_len = STRLENOF( "(entryUUID=)" ) + syncUUID_strrep.bv_len;
@@ -1765,8 +1662,25 @@ syncrepl_entry(
                        ber_memfree( a->a_vals[0].bv_val );
                        ber_dupbv( &a->a_vals[0], &syncUUID_strrep );
                }
+               /* Don't save the contextCSN on the inooming context entry,
+                * we'll write it when syncrepl_updateCookie eventually
+                * gets called. (ITS#4622)
+                */
+               if ( syncstate == LDAP_SYNC_ADD && dn_match( &entry->e_nname,
+                       &be->be_nsuffix[0] )) {
+                       Attribute **ap;
+                       for ( ap = &entry->e_attrs; *ap; ap=&(*ap)->a_next ) {
+                               a = *ap;
+                               if ( a->a_desc == slap_schema.si_ad_contextCSN ) {
+                                       *ap = a->a_next;
+                                       attr_free( a );
+                                       break;
+                               }
+                       }
+               }
        }
 
+       slap_op_time( &op->o_time, &op->o_tincr );
        switch ( syncstate ) {
        case LDAP_SYNC_ADD:
        case LDAP_SYNC_MODIFY:
@@ -1845,6 +1759,7 @@ retry_add:;
                                        if ( rc ) goto done;
 
                                        retry = 0;
+                                       slap_op_time( &op->o_time, &op->o_tincr );
                                        goto retry_add;
                                }
                                /* FALLTHRU */
@@ -1879,7 +1794,17 @@ retry_add:;
                        if (( rc = slap_modrdn2mods( op, &rs_modify ))) {
                                goto done;
                        }
+
+                       /* RDNs must be NUL-terminated for back-ldap */
+                       noldp = op->orr_newrdn;
+                       ber_dupbv_x( &op->orr_newrdn, &noldp, op->o_tmpmemctx );
+                       noldp = op->orr_nnewrdn;
+                       ber_dupbv_x( &op->orr_nnewrdn, &noldp, op->o_tmpmemctx );
+
                        rc = be->be_modrdn( op, &rs_modify );
+                       op->o_tmpfree( op->orr_nnewrdn.bv_val, op->o_tmpmemctx );
+                       op->o_tmpfree( op->orr_newrdn.bv_val, op->o_tmpmemctx );
+
                        slap_mods_free( op->orr_modlist, 1 );
                        Debug( LDAP_DEBUG_SYNC,
                                        "syncrepl_entry: %s (%d)\n", 
@@ -1890,6 +1815,8 @@ retry_add:;
                        } else {
                                goto done;
                        }
+                       if ( dni.wasChanged )
+                               slap_op_time( &op->o_time, &op->o_tincr );
                }
                if ( dni.wasChanged ) {
                        Modifications *mod, *modhead = NULL;
@@ -2020,7 +1947,8 @@ static void
 syncrepl_del_nonpresent(
        Operation *op,
        syncinfo_t *si,
-       BerVarray uuids )
+       BerVarray uuids,
+       struct berval *cookiecsn )
 {
        Backend* be = op->o_bd;
        slap_callback   cb = { NULL };
@@ -2032,6 +1960,7 @@ syncrepl_del_nonpresent(
        AttributeName   an[2];
 
        struct berval pdn = BER_BVNULL;
+       struct berval csn;
 
        op->o_req_dn = si->si_base;
        op->o_req_ndn = si->si_base;
@@ -2098,7 +2027,12 @@ syncrepl_del_nonpresent(
 
        if ( !LDAP_LIST_EMPTY( &si->si_nonpresentlist ) ) {
 
-               slap_queue_csn( op, &si->si_syncCookie.ctxcsn );
+               if ( cookiecsn && !BER_BVISNULL( cookiecsn ))
+                       csn = *cookiecsn;
+               else
+                       csn = si->si_syncCookie.ctxcsn;
+
+               slap_queue_csn( op, &csn );
 
                np_list = LDAP_LIST_FIRST( &si->si_nonpresentlist );
                while ( np_list != NULL ) {
@@ -2245,12 +2179,11 @@ syncrepl_add_glue(
        }
 
        while ( ndn.bv_val > e->e_nname.bv_val ) {
-               glue = (Entry *) ch_calloc( 1, sizeof(Entry) );
+               glue = entry_alloc();
                ber_dupbv( &glue->e_name, &dn );
                ber_dupbv( &glue->e_nname, &ndn );
 
-               a = ch_calloc( 1, sizeof( Attribute ));
-               a->a_desc = slap_schema.si_ad_objectClass;
+               a = attr_alloc( slap_schema.si_ad_objectClass );
 
                a->a_vals = ch_calloc( 3, sizeof( struct berval ));
                ber_dupbv( &a->a_vals[0], &gcbva[0] );
@@ -2262,8 +2195,7 @@ syncrepl_add_glue(
                a->a_next = glue->e_attrs;
                glue->e_attrs = a;
 
-               a = ch_calloc( 1, sizeof( Attribute ));
-               a->a_desc = slap_schema.si_ad_structuralObjectClass;
+               a = attr_alloc( slap_schema.si_ad_structuralObjectClass );
 
                a->a_vals = ch_calloc( 2, sizeof( struct berval ));
                ber_dupbv( &a->a_vals[0], &gcbva[1] );
@@ -2496,10 +2428,14 @@ nonpresent_callback(
                if ( !(si->si_refreshDelete & NP_DELETE_ONE )) {
                        a = attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID );
 
-                       if ( a == NULL ) return 0;
+                       if ( a )
+                               present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
+                                       syncuuid_cmp );
+
+                       Debug( LDAP_DEBUG_SYNC, "nonpresent_callback: UUID %s, dn %s, %sfound\n",
+                               a ? a->a_vals[0].bv_val : "<missing>", rs->sr_entry->e_name.bv_val, present_uuid ? "" : "not " );
 
-                       present_uuid = avl_find( si->si_presentlist, &a->a_nvals[0],
-                               syncuuid_cmp );
+                       if ( a == NULL ) return 0;
                }
 
                if ( present_uuid == NULL ) {
@@ -2747,10 +2683,11 @@ syncinfo_free( syncinfo_t *sie )
 
 /* mandatory */
 #define GOT_ID                 0x0001
-#define GOT_PROVIDER           0x0002
+#define GOT_PROVIDER   0x0002
+#define        GOT_BASE                0x0004
 
 /* check */
-#define GOT_ALL                        (GOT_ID|GOT_PROVIDER)
+#define GOT_ALL                        (GOT_ID|GOT_PROVIDER|GOT_BASE)
 
 static struct {
        struct berval key;
@@ -2856,6 +2793,7 @@ parse_syncrepl_line(
                                Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                                return -1;
                        }
+                       gots |= GOT_BASE;
                } else if ( !strncasecmp( c->argv[ i ], LOGBASESTR "=",
                                        STRLENOF( LOGBASESTR "=" ) ) )
                {
@@ -2982,8 +2920,11 @@ parse_syncrepl_line(
                        } else if ( strchr( val, ':' ) != NULL ) {
                                char *next, *ptr = val;
                                unsigned dd, hh, mm, ss;
+
+                               /* NOTE: the test for ptr[ 0 ] == '-'
+                                * should go before the call to strtoul() */
                                dd = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != ':' ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse days", val );
@@ -2992,7 +2933,7 @@ parse_syncrepl_line(
                                }
                                ptr = next + 1;
                                hh = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != ':' || hh > 24 ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || hh > 24 ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse hours", val );
@@ -3001,7 +2942,7 @@ parse_syncrepl_line(
                                }
                                ptr = next + 1;
                                mm = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != ':' || mm > 60 ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != ':' || mm > 60 ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse minutes", val );
@@ -3010,7 +2951,7 @@ parse_syncrepl_line(
                                }
                                ptr = next + 1;
                                ss = strtoul( ptr, &next, 10 );
-                               if ( next == ptr || next[0] != '\0' || ss > 60 ) {
+                               if ( ptr[ 0 ] == '-' || next == ptr || next[0] != '\0' || ss > 60 ) {
                                        snprintf( c->msg, sizeof( c->msg ),
                                                "Error: parse_syncrepl_line: "
                                                "invalid interval \"%s\", unable to parse seconds", val );
@@ -3169,7 +3110,10 @@ parse_syncrepl_line(
 
        if ( gots != GOT_ALL ) {
                snprintf( c->msg, sizeof( c->msg ),
-                       "Error: Malformed \"syncrepl\" line in slapd config file" );
+                       "Error: Malformed \"syncrepl\" line in slapd config file, missing%s%s%s",
+                       gots & GOT_ID ? "" : " "IDSTR,
+                       gots & GOT_PROVIDER ? "" : " "PROVIDERSTR,
+                       gots & GOT_BASE ? "" : " "SEARCHBASESTR );
                Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
                return -1;
        }
@@ -3185,8 +3129,14 @@ add_syncrepl(
        int     rc = 0;
 
        if ( !( c->be->be_search && c->be->be_add && c->be->be_modify && c->be->be_delete ) ) {
-               Debug( LDAP_DEBUG_ANY, "%s: database %s does not support operations "
-                       "required for syncrepl\n", c->log, c->be->be_type, 0 );
+               snprintf( c->msg, sizeof(c->msg), "database %s does not support "
+                       "operations required for syncrepl", c->be->be_type );
+               Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
+               return 1;
+       }
+       if ( BER_BVISEMPTY( &c->be->be_rootdn )) {
+               strcpy( c->msg, "rootDN must be defined before syncrepl may be used" );
+               Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->msg, 0 );
                return 1;
        }
        si = (syncinfo_t *) ch_calloc( 1, sizeof( syncinfo_t ) );
@@ -3220,10 +3170,6 @@ add_syncrepl(
        si->si_slimit = 0;
        si->si_conn_setup = 0;
 
-#ifdef HAVE_TLS
-       si->si_check_tls = 1;
-#endif
-
        si->si_presentlist = NULL;
        LDAP_LIST_INIT( &si->si_nonpresentlist );
        ldap_pvt_thread_mutex_init( &si->si_mutex );