syncrepl.c 93.1 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* syncrepl.c -- Replication Engine which uses the LDAP Sync protocol */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
5
 * Copyright 2003-2008 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
 * Portions Copyright 2003 by IBM Corporation.
 * Portions Copyright 2003 by Howard Chu, Symas Corporation.
 * All rights reserved.
9
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
10
11
12
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
13
 *
Kurt Zeilenga's avatar
Kurt Zeilenga committed
14
15
16
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
17
 */
18
19
20
21
22
23
24
25
26
27
28
29

#include "portable.h"

#include <stdio.h>

#include <ac/string.h>
#include <ac/socket.h>

#include "lutil.h"
#include "slap.h"
#include "lutil_ldap.h"

30
31
#include "config.h"

32
33
#include "ldap_rq.h"

34
35
36
37
38
39
struct nonpresent_entry {
	struct berval *npe_name;
	struct berval *npe_nname;
	LDAP_LIST_ENTRY(nonpresent_entry) npe_link;
};

Kurt Zeilenga's avatar
Kurt Zeilenga committed
40
41
42
43
#define	SYNCDATA_DEFAULT	0	/* entries are plain LDAP entries */
#define	SYNCDATA_ACCESSLOG	1	/* entries are accesslog format */
#define	SYNCDATA_CHANGELOG	2	/* entries are changelog format */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
44
45
46
#define	SYNCLOG_LOGGING		0	/* doing a log-based update */
#define	SYNCLOG_FALLBACK	1	/* doing a full refresh */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
47
48
49
50
51
#define RETRYNUM_FOREVER	(-1)	/* retry forever */
#define RETRYNUM_TAIL		(-2)	/* end of retrynum array */
#define RETRYNUM_VALID(n)	((n) >= RETRYNUM_FOREVER)	/* valid retrynum */
#define RETRYNUM_FINITE(n)	((n) > RETRYNUM_FOREVER)	/* not forever */

52
53
54
typedef struct syncinfo_s {
	struct slap_backend_db *si_be;
	struct re_s			*si_re;
55
	int					si_rid;
56
57
	slap_bindconf		si_bindconf;
	struct berval		si_base;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
58
59
60
	struct berval		si_logbase;
	struct berval		si_filterstr;
	struct berval		si_logfilterstr;
61
62
63
64
65
66
67
68
69
70
	int					si_scope;
	int					si_attrsonly;
	char				*si_anfile;
	AttributeName		*si_anlist;
	AttributeName		*si_exanlist;
	char 				**si_attrs;
	char				**si_exattrs;
	int					si_allattrs;
	int					si_allopattrs;
	int					si_schemachecking;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
71
72
	int					si_type;	/* the active type */
	int					si_ctype;	/* the configured type */
73
74
75
76
77
78
79
80
81
82
	time_t				si_interval;
	time_t				*si_retryinterval;
	int					*si_retrynum_init;
	int					*si_retrynum;
	struct sync_cookie	si_syncCookie;
	int					si_manageDSAit;
	int					si_slimit;
	int					si_tlimit;
	int					si_refreshDelete;
	int					si_refreshPresent;
Howard Chu's avatar
Howard Chu committed
83
	int					si_refreshDone;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
84
	int					si_syncdata;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
85
86
	int					si_logstate;
	int					si_conn_setup;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
87
	ber_int_t				si_msgid;
88
89
90
91
92
93
	Avlnode				*si_presentlist;
	LDAP				*si_ld;
	LDAP_LIST_HEAD(np, nonpresent_entry) si_nonpresentlist;
	ldap_pvt_thread_mutex_t	si_mutex;
} syncinfo_t;

94
static int syncuuid_cmp( const void *, const void * );
95
static void avl_ber_bvfree( void * );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
96
static void syncrepl_del_nonpresent( Operation *, syncinfo_t *, BerVarray, struct berval * );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
97
98
static int syncrepl_message_to_op(
					syncinfo_t *, Operation *, LDAPMessage * );
99
100
101
102
103
104
105
106
107
108
109
110
111
static int syncrepl_message_to_entry(
					syncinfo_t *, Operation *, LDAPMessage *,
					Modifications **, Entry **, int );
static int syncrepl_entry(
					syncinfo_t *, Operation*, Entry*,
					Modifications**,int, struct berval*,
					struct sync_cookie *,
					struct berval * );
static void syncrepl_updateCookie(
					syncinfo_t *, Operation *, struct berval *,
					struct sync_cookie * );
static struct berval * slap_uuidstr_from_normalized(
					struct berval *, struct berval *, void * );
112

113
/* callback functions */
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
114
static int dn_callback( struct slap_op *, struct slap_rep * );
115
116
static int nonpresent_callback( struct slap_op *, struct slap_rep * );
static int null_callback( struct slap_op *, struct slap_rep * );
117

118
static AttributeDescription *sync_descs[4];
119

120
static void
121
init_syncrepl(syncinfo_t *si)
122
{
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
123
	int i, j, k, l, n;
124
	char **attrs, **exattrs;
125
126
127
128
129
130
131
132

	if ( !sync_descs[0] ) {
		sync_descs[0] = slap_schema.si_ad_objectClass;
		sync_descs[1] = slap_schema.si_ad_structuralObjectClass;
		sync_descs[2] = slap_schema.si_ad_entryCSN;
		sync_descs[3] = NULL;
	}

133
134
135
136
	if ( si->si_allattrs && si->si_allopattrs )
		attrs = NULL;
	else
		attrs = anlist2attrs( si->si_anlist );
137

138
139
140
141
142
143
144
145
146
	if ( attrs ) {
		if ( si->si_allattrs ) {
			i = 0;
			while ( attrs[i] ) {
				if ( !is_at_operational( at_find( attrs[i] ))) {
					for ( j = i; attrs[j] != NULL; j++ ) {
						if ( j == i )
							ch_free( attrs[i] );
						attrs[j] = attrs[j+1];
147
					}
148
149
				} else {
					i++;
150
151
				}
			}
152
			attrs = ( char ** ) ch_realloc( attrs, (i + 2)*sizeof( char * ) );
153
154
			attrs[i] = ch_strdup("*");
			attrs[i + 1] = NULL;
155

156
157
158
159
160
161
162
163
164
165
166
167
168
		} else if ( si->si_allopattrs ) {
			i = 0;
			while ( attrs[i] ) {
				if ( is_at_operational( at_find( attrs[i] ))) {
					for ( j = i; attrs[j] != NULL; j++ ) {
						if ( j == i )
							ch_free( attrs[i] );
						attrs[j] = attrs[j+1];
					}
				} else {
					i++;
				}
			}
169
			attrs = ( char ** ) ch_realloc( attrs, (i + 2)*sizeof( char * ) );
170
171
			attrs[i] = ch_strdup("+");
			attrs[i + 1] = NULL;
172
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
173

174
175
176
177
178
179
180
181
		for ( i = 0; sync_descs[i] != NULL; i++ ) {
			j = 0;
			while ( attrs[j] ) {
				if ( !strcmp( attrs[j], sync_descs[i]->ad_cname.bv_val )) {
					for ( k = j; attrs[k] != NULL; k++ ) {
						if ( k == j )
							ch_free( attrs[k] );
						attrs[k] = attrs[k+1];
182
					}
183
184
				} else {
					j++;
185
186
				}
			}
187
188
189
190
191
192
193
		}

		for ( n = 0; attrs[ n ] != NULL; n++ ) /* empty */;

		if ( si->si_allopattrs ) {
			attrs = ( char ** ) ch_realloc( attrs, (n + 2)*sizeof( char * ));
		} else {
194
			attrs = ( char ** ) ch_realloc( attrs, (n + 4)*sizeof( char * ));
195
196
197
		}

		if ( attrs == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
198
			Debug( LDAP_DEBUG_ANY, "out of memory\n", 0, 0, 0 );
199
200
201
202
203
204
		}

		/* Add Attributes */
		if ( si->si_allopattrs ) {
			attrs[n++] = ch_strdup( sync_descs[0]->ad_cname.bv_val );
		} else {
205
206
207
			for ( i = 0; sync_descs[ i ] != NULL; i++ ) {
				attrs[ n++ ] = ch_strdup ( sync_descs[i]->ad_cname.bv_val );
			}
208
		}
209
		attrs[ n ] = NULL;
210

211
	} else {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
212

213
		i = 0;
214
215
		if ( si->si_allattrs == si->si_allopattrs ) {
			attrs = (char**) ch_malloc( 3 * sizeof(char*) );
216
217
			attrs[i++] = ch_strdup( "*" );
			attrs[i++] = ch_strdup( "+" );
218
219
220
221
222
223
		} else if ( si->si_allattrs && !si->si_allopattrs ) {
			for ( n = 0; sync_descs[ n ] != NULL; n++ ) ;
			attrs = (char**) ch_malloc( (n+1)* sizeof(char*) );
			attrs[i++] = ch_strdup( "*" );
			for ( j = 1; sync_descs[ j ] != NULL; j++ ) {
				attrs[i++] = ch_strdup ( sync_descs[j]->ad_cname.bv_val );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
224
			}
225
226
227
228
		} else if ( !si->si_allattrs && si->si_allopattrs ) {
			attrs = (char**) ch_malloc( 3 * sizeof(char*) );
			attrs[i++] = ch_strdup( "+" );
			attrs[i++] = ch_strdup( sync_descs[0]->ad_cname.bv_val );
229
230
		}
		attrs[i] = NULL;
231
232
	}
	
233
234
235
236
237
	si->si_attrs = attrs;

	exattrs = anlist2attrs( si->si_exanlist );

	if ( exattrs ) {
238
239
		for ( n = 0; exattrs[n] != NULL; n++ ) ;

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
240
		for ( i = 0; sync_descs[i] != NULL; i++ ) {
241
242
243
			j = 0;
			while ( exattrs[j] != NULL ) {
				if ( !strcmp( exattrs[j], sync_descs[i]->ad_cname.bv_val )) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
244
					ch_free( exattrs[j] );
245
246
					for ( k = j; exattrs[k] != NULL; k++ ) {
						exattrs[k] = exattrs[k+1];
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
247
					}
248
249
				} else {
					j++;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
250
251
252
				}
			}
		}
253
254
255

		for ( i = 0; exattrs[i] != NULL; i++ ) {
			for ( j = 0; si->si_anlist[j].an_name.bv_val; j++ ) {
256
257
				ObjectClass	*oc;
				if ( ( oc = si->si_anlist[j].an_oc ) ) {
258
259
260
261
					k = 0;
					while ( oc->soc_required[k] ) {
						if ( !strcmp( exattrs[i],
							 oc->soc_required[k]->sat_cname.bv_val )) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
262
							ch_free( exattrs[i] );
263
264
265
266
267
							for ( l = i; exattrs[l]; l++ ) {
								exattrs[l] = exattrs[l+1];
							}
						} else {
							k++;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
268
269
270
271
272
						}
					}
				}
			}
		}
273
274

		for ( i = 0; exattrs[i] != NULL; i++ ) ;
275
276
277

		if ( i != n )
			exattrs = (char **) ch_realloc( exattrs, (i + 1)*sizeof(char *));
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
278
	}
279
280

	si->si_exattrs = exattrs;	
281
282
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
typedef struct logschema {
	struct berval ls_dn;
	struct berval ls_req;
	struct berval ls_mod;
	struct berval ls_newRdn;
	struct berval ls_delRdn;
	struct berval ls_newSup;
} logschema;

static logschema changelog_sc = {
	BER_BVC("targetDN"),
	BER_BVC("changeType"),
	BER_BVC("changes"),
	BER_BVC("newRDN"),
	BER_BVC("deleteOldRDN"),
	BER_BVC("newSuperior")
};

static logschema accesslog_sc = {
	BER_BVC("reqDN"),
	BER_BVC("reqType"),
	BER_BVC("reqMod"),
	BER_BVC("reqNewRDN"),
	BER_BVC("reqDeleteOldRDN"),
	BER_BVC("reqNewSuperior")
};

310
static int
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
311
312
ldap_sync_search(
	syncinfo_t *si,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
313
	void *ctx )
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
314
{
315
316
317
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	LDAPControl c[2], *ctrls[3];
318
	struct timeval timeout;
319
	int rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
320
321
322
323
324
325
	int rhint;
	char *base;
	char **attrs, *lattrs[8];
	char *filter;
	int attrsonly;
	int scope;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
326

327
328
329
	/* setup LDAP SYNC control */
	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &ctx );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
330

Kurt Zeilenga's avatar
Kurt Zeilenga committed
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
	/* If we're using a log but we have no state, then fallback to
	 * normal mode for a full refresh.
	 */
	if ( si->si_syncdata && BER_BVISEMPTY( &si->si_syncCookie.ctxcsn ))
		si->si_logstate = SYNCLOG_FALLBACK;

	/* Use the log parameters if we're in log mode */
	if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) {
		logschema *ls;
		if ( si->si_syncdata == SYNCDATA_ACCESSLOG )
			ls = &accesslog_sc;
		else
			ls = &changelog_sc;
		lattrs[0] = ls->ls_dn.bv_val;
		lattrs[1] = ls->ls_req.bv_val;
		lattrs[2] = ls->ls_mod.bv_val;
		lattrs[3] = ls->ls_newRdn.bv_val;
		lattrs[4] = ls->ls_delRdn.bv_val;
		lattrs[5] = ls->ls_newSup.bv_val;
		lattrs[6] = slap_schema.si_ad_entryCSN->ad_cname.bv_val;
		lattrs[7] = NULL;

		rhint = 0;
		base = si->si_logbase.bv_val;
		filter = si->si_logfilterstr.bv_val;
		attrs = lattrs;
		attrsonly = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
358
		scope = LDAP_SCOPE_SUBTREE;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
359
360
361
362
363
364
365
366
367
368
369
370
371
372
	} else {
		rhint = 1;
		base = si->si_base.bv_val;
		filter = si->si_filterstr.bv_val;
		attrs = si->si_attrs;
		attrsonly = si->si_attrsonly;
		scope = si->si_scope;
	}
	if ( si->si_syncdata && si->si_logstate == SYNCLOG_FALLBACK ) {
		si->si_type = LDAP_SYNC_REFRESH_ONLY;
	} else {
		si->si_type = si->si_ctype;
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
373
	if ( !BER_BVISNULL( &si->si_syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
374
	{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
375
376
		ber_printf( ber, "{eOb}",
			abs(si->si_type), &si->si_syncCookie.octet_str, rhint );
377
	} else {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
378
379
		ber_printf( ber, "{eb}",
			abs(si->si_type), rhint );
380
	}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
381

382
383
384
385
	if ( (rc = ber_flatten2( ber, &c[0].ldctl_value, 0 )) == LBER_ERROR ) {
		ber_free_buf( ber );
		return rc;
	}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
386

387
	c[0].ldctl_oid = LDAP_CONTROL_SYNC;
388
	c[0].ldctl_iscritical = si->si_type < 0;
389
	ctrls[0] = &c[0];
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
390

391
	if ( !BER_BVISNULL( &si->si_bindconf.sb_authzId ) ) {
392
		c[1].ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
393
		c[1].ldctl_value = si->si_bindconf.sb_authzId;
394
395
396
397
398
399
		c[1].ldctl_iscritical = 1;
		ctrls[1] = &c[1];
		ctrls[2] = NULL;
	} else {
		ctrls[1] = NULL;
	}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
400

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
401
	timeout.tv_sec = si->si_tlimit;
402
	timeout.tv_usec = 0;
403

Kurt Zeilenga's avatar
Kurt Zeilenga committed
404
	rc = ldap_search_ext( si->si_ld, base, scope, filter, attrs, attrsonly,
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
405
		ctrls, NULL, si->si_tlimit > 0 ? &timeout : NULL,
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
406
		si->si_slimit, &si->si_msgid );
407
	ber_free_buf( ber );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
408
409
410
	return rc;
}

411
412
413
414
static int
do_syncrep1(
	Operation *op,
	syncinfo_t *si )
415
416
{
	int	rc;
417
	int cmdline_cookie_found = 0;
418

419
	struct sync_cookie	*sc = NULL;
420
	struct berval	*psub;
421
422
423
#ifdef HAVE_TLS
	void	*ssl;
#endif
424
425

	psub = &si->si_be->be_nsuffix[0];
426
427

	/* Init connection to master */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
428
	rc = ldap_initialize( &si->si_ld, si->si_bindconf.sb_uri.bv_val );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
429
	if ( rc != LDAP_SUCCESS ) {
430
		Debug( LDAP_DEBUG_ANY,
431
432
			"do_syncrep1: rid %03d ldap_initialize failed (%s)\n",
			si->si_rid, si->si_bindconf.sb_uri.bv_val, 0 );
433
		return rc;
434
435
	}

436
437
	op->o_protocol = LDAP_VERSION3;
	ldap_set_option( si->si_ld, LDAP_OPT_PROTOCOL_VERSION, &op->o_protocol );
438
439
440

	/* Bind to master */

Kurt Zeilenga's avatar
Kurt Zeilenga committed
441
	if ( si->si_bindconf.sb_tls ) {
442
		rc = ldap_start_tls_s( si->si_ld, NULL, NULL );
443
444
		if( rc != LDAP_SUCCESS ) {
			Debug( LDAP_DEBUG_ANY,
445
				"%s: rid %03d ldap_start_tls failed (%d)\n",
Kurt Zeilenga's avatar
Kurt Zeilenga committed
446
				si->si_bindconf.sb_tls == SB_TLS_CRITICAL ? "Error" : "Warning",
447
				si->si_rid, rc );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
448
			if( si->si_bindconf.sb_tls == SB_TLS_CRITICAL ) goto done;
449
450
451
		}
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
452
	if ( si->si_bindconf.sb_method == LDAP_AUTH_SASL ) {
453
454
455
#ifdef HAVE_CYRUS_SASL
		void *defaults;

Kurt Zeilenga's avatar
Kurt Zeilenga committed
456
		if ( si->si_bindconf.sb_secprops != NULL ) {
457
			rc = ldap_set_option( si->si_ld,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
458
				LDAP_OPT_X_SASL_SECPROPS, si->si_bindconf.sb_secprops);
459

460
			if( rc != LDAP_OPT_SUCCESS ) {
461
				Debug( LDAP_DEBUG_ANY, "Error: rid %03d ldap_set_option "
462
					"(%s,SECPROPS,\"%s\") failed!\n",
463
					si->si_rid, si->si_bindconf.sb_uri.bv_val, si->si_bindconf.sb_secprops );
464
				goto done;
465
466
467
			}
		}

468
469
470
471
472
473
		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 );
474

475
		rc = ldap_sasl_interactive_bind_s( si->si_ld,
476
477
				si->si_bindconf.sb_binddn.bv_val,
				si->si_bindconf.sb_saslmech.bv_val,
478
				NULL, NULL,
479
				LDAP_SASL_QUIET,
480
481
482
				lutil_sasl_interact,
				defaults );

483
484
		lutil_sasl_freedefs( defaults );

485
		/* FIXME: different error behaviors according to
486
487
488
		 *	1) return code
		 *	2) on err policy : exit, retry, backoff ...
		 */
489
		if ( rc != LDAP_SUCCESS ) {
490
491
			static struct berval bv_GSSAPI = BER_BVC( "GSSAPI" );

492
			Debug( LDAP_DEBUG_ANY, "do_syncrep1: rid %03d "
493
				"ldap_sasl_interactive_bind_s failed (%d)\n",
494
				si->si_rid, rc, 0 );
495
496
497

			/* FIXME (see above comment) */
			/* if Kerberos credentials cache is not active, retry */
498
			if ( ber_bvcmp( &si->si_bindconf.sb_saslmech, &bv_GSSAPI ) == 0 &&
499
500
501
502
503
				rc == LDAP_LOCAL_ERROR )
			{
				rc = LDAP_SERVER_DOWN;
			}

504
			goto done;
505
506
		}
#else /* HAVE_CYRUS_SASL */
507
		/* Should never get here, we trapped this at config time */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
508
		assert(0);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
509
		Debug( LDAP_DEBUG_SYNC, "not compiled with SASL support\n", 0, 0, 0 );
510
511
		rc = LDAP_OTHER;
		goto done;
512
#endif
Kurt Zeilenga's avatar
Kurt Zeilenga committed
513

514
515
516
517
	} 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 );
518
		if ( rc != LDAP_SUCCESS ) {
519
520
			Debug( LDAP_DEBUG_ANY, "do_syncrep1: rid %03d "
				"ldap_sasl_bind_s failed (%d)\n", si->si_rid, rc, 0 );
521
			goto done;
522
523
524
		}
	}

525
526
527
	/* Set SSF to strongest of TLS, SASL SSFs */
	op->o_sasl_ssf = 0;
	op->o_tls_ssf = 0;
528
	op->o_transport_ssf = 0;
529
#ifdef HAVE_TLS
530
531
532
	if ( ldap_get_option( si->si_ld, LDAP_OPT_X_TLS_SSL_CTX, &ssl )
		== LDAP_SUCCESS && ssl != NULL )
	{
533
534
535
536
		op->o_tls_ssf = ldap_pvt_tls_get_strength( ssl );
	}
#endif /* HAVE_TLS */
	ldap_get_option( si->si_ld, LDAP_OPT_X_SASL_SSF, &op->o_sasl_ssf );
537
538
	op->o_ssf = ( op->o_sasl_ssf > op->o_tls_ssf )
		?  op->o_sasl_ssf : op->o_tls_ssf;
539

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
540

Kurt Zeilenga's avatar
Kurt Zeilenga committed
541
542
543
	if ( BER_BVISNULL( &si->si_syncCookie.octet_str )) {
		/* get contextCSN shadow replica from database */
		BerVarray csn = NULL;
544

Kurt Zeilenga's avatar
Kurt Zeilenga committed
545
546
547
		assert( si->si_rid < 1000 );
		op->o_req_ndn = op->o_bd->be_nsuffix[0];
		op->o_req_dn = op->o_req_ndn;
548

Kurt Zeilenga's avatar
Kurt Zeilenga committed
549
		/* try to read stored contextCSN */
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
550
		backend_attribute( op, NULL, &op->o_req_ndn,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
551
552
553
554
555
556
			slap_schema.si_ad_contextCSN, &csn, ACL_READ );
		if ( csn ) {
			ch_free( si->si_syncCookie.ctxcsn.bv_val );
			ber_dupbv( &si->si_syncCookie.ctxcsn, csn );
			ber_bvarray_free_x( csn, op->o_tmpmemctx );
		}
557

Kurt Zeilenga's avatar
Kurt Zeilenga committed
558
559
560
561
562
563
564
565
566
567
568
569
570
571
		si->si_syncCookie.rid = si->si_rid;

		LDAP_STAILQ_FOREACH( sc, &slap_sync_cookie, sc_next ) {
			if ( si->si_rid == sc->rid ) {
				cmdline_cookie_found = 1;
				break;
			}
		}

		if ( cmdline_cookie_found ) {
			/* cookie is supplied in the command line */

			LDAP_STAILQ_REMOVE( &slap_sync_cookie, sc, sync_cookie, sc_next );

Kurt Zeilenga's avatar
Kurt Zeilenga committed
572
573
			/* ctxcsn wasn't parsed yet, do it now */
			slap_parse_sync_cookie( sc, op->o_tmpmemctx );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
574
			if ( BER_BVISNULL( &sc->ctxcsn ) ) {
575
576
577
				/* if cmdline cookie does not have ctxcsn */
				/* component, set it to an initial value */
				slap_init_sync_cookie_ctxcsn( sc );
578
			}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
579
			slap_sync_cookie_free( &si->si_syncCookie, 0 );
580
581
			slap_dup_sync_cookie( &si->si_syncCookie, sc );
			slap_sync_cookie_free( sc, 1 );
582
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
583

Kurt Zeilenga's avatar
Kurt Zeilenga committed
584
585
		slap_compose_sync_cookie( NULL, &si->si_syncCookie.octet_str,
			&si->si_syncCookie.ctxcsn, si->si_syncCookie.rid );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
586
587
	}

Howard Chu's avatar
Howard Chu committed
588
589
	si->si_refreshDone = 0;

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
590
	rc = ldap_sync_search( si, op->o_tmpmemctx );
591

592
	if( rc != LDAP_SUCCESS ) {
593
594
595
		Debug( LDAP_DEBUG_ANY, "do_syncrep1: rid %03d "
			"ldap_search_ext: %s (%d)\n",
			si->si_rid, ldap_err2string( rc ), rc );
596
597
598
599
600
	}

done:
	if ( rc ) {
		if ( si->si_ld ) {
601
			ldap_unbind_ext( si->si_ld, NULL, NULL );
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
			si->si_ld = NULL;
		}
	}

	return rc;
}

static int
do_syncrep2(
	Operation *op,
	syncinfo_t *si )
{
	LDAPControl	**rctrls = NULL;
	LDAPControl	*rctrlp;

	BerElementBuffer berbuf;
	BerElement	*ber = (BerElement *)&berbuf;

	LDAPMessage	*res = NULL;
	LDAPMessage	*msg = NULL;

	char		*retoid = NULL;
	struct berval	*retdata = NULL;

	Entry		*entry = NULL;

	int		syncstate;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
629
	struct berval	syncUUID = BER_BVNULL;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
630
631
	struct sync_cookie	syncCookie = { BER_BVNULL };
	struct sync_cookie	syncCookie_req = { BER_BVNULL };
Kurt Zeilenga's avatar
Kurt Zeilenga committed
632
	struct berval		cookie = BER_BVNULL;
633

634
	int	rc, err, i;
635
636
637
638
639
640
641
642
643
644
645
	ber_len_t	len;

	struct berval	*psub;
	Modifications	*modlist = NULL;

	const char		*text;
	int				match;

	struct timeval *tout_p = NULL;
	struct timeval tout = { 0, 0 };

646
	int		refreshDeletes = 0;
647
	BerVarray syncUUIDs = NULL;
648
649
	ber_tag_t si_tag;

650
	if ( slapd_shutdown ) {
651
		rc = -2;
652
		goto done;
653
654
	}

655
656
657
	ber_init2( ber, NULL, LBER_USE_DER );
	ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

658
	Debug( LDAP_DEBUG_TRACE, "=>do_syncrep2 rid %03d\n", si->si_rid, 0, 0 );
659
660
661

	psub = &si->si_be->be_nsuffix[0];

Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
662
	slap_dup_sync_cookie( &syncCookie_req, &si->si_syncCookie );
663

Kurt Zeilenga's avatar
Kurt Zeilenga committed
664
	if ( abs(si->si_type) == LDAP_SYNC_REFRESH_AND_PERSIST ) {
665
666
667
668
669
		tout_p = &tout;
	} else {
		tout_p = NULL;
	}

Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
670
	while (( rc = ldap_result( si->si_ld, si->si_msgid, LDAP_MSG_ONE,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
671
		tout_p, &res )) > 0 )
672
	{
673
		if ( slapd_shutdown ) {
674
675
			rc = -2;
			goto done;
676
		}
677
		for( msg = ldap_first_message( si->si_ld, res );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
678
679
			msg != NULL;
			msg = ldap_next_message( si->si_ld, msg ) )
680
		{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
681
682
683
684
			if ( slapd_shutdown ) {
				rc = -2;
				goto done;
			}
685
686
			switch( ldap_msgtype( msg ) ) {
			case LDAP_RES_SEARCH_ENTRY:
687
				ldap_get_entry_controls( si->si_ld, msg, &rctrls );
Howard Chu's avatar
Howard Chu committed
688
689
				/* we can't work without the control */
				if ( !rctrls ) {
690
					Debug( LDAP_DEBUG_ANY, "do_syncrep2: rid %03d"
691
						"got search entry without "
692
						"control\n", si->si_rid, 0, 0 );
Howard Chu's avatar
Howard Chu committed
693
694
695
696
697
					rc = -1;
					goto done;
				}
				rctrlp = *rctrls;
				ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
698
				ber_scanf( ber, "{em" /*"}"*/, &syncstate, &syncUUID );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
699
700
701
				/* FIXME: what if syncUUID is NULL or empty?
				 * (happens with back-sql...) */
				if ( BER_BVISEMPTY( &syncUUID ) ) {
702
703
					Debug( LDAP_DEBUG_ANY, "do_syncrep2: rid %03d "
						"got empty syncUUID\n", si->si_rid, 0, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
704
					ldap_controls_free( rctrls );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
705
706
707
					rc = -1;
					goto done;
				}
708
				if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
709
					ber_scanf( ber, /*"{"*/ "m}", &cookie );
710
					if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
711
712
						ch_free( syncCookie.octet_str.bv_val );
						ber_dupbv( &syncCookie.octet_str, &cookie );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
713
					}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
714
					if ( !BER_BVISNULL( &syncCookie.octet_str ) )
715
					{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
716
						slap_parse_sync_cookie( &syncCookie, NULL );
717
					}
718
				}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
719
				rc = 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
720
				if ( si->si_syncdata && si->si_logstate == SYNCLOG_LOGGING ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
721
					modlist = NULL;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
722
					if (( rc = syncrepl_message_to_op( si, op, msg )) == LDAP_SUCCESS &&
Kurt Zeilenga's avatar
Kurt Zeilenga committed
723
724
						!BER_BVISNULL( &syncCookie.ctxcsn ) ) {
						syncrepl_updateCookie( si, op, psub, &syncCookie );
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
725
726
727
728
729
730
731
732
733
734
735
					} else switch ( rc ) {
						case LDAP_ALREADY_EXISTS:
						case LDAP_NO_SUCH_OBJECT:
						case LDAP_NO_SUCH_ATTRIBUTE:
						case LDAP_TYPE_OR_VALUE_EXISTS:
							rc = LDAP_SYNC_REFRESH_REQUIRED;
							si->si_logstate = SYNCLOG_FALLBACK;
							ldap_abandon_ext( si->si_ld, si->si_msgid, NULL, NULL );
							break;
						default:
							break;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
736
					}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
737
738
739
740
741
742
				} else if (( rc = syncrepl_message_to_entry( si, op, msg,
					&modlist, &entry, syncstate )) == LDAP_SUCCESS ) {
					if (( rc = syncrepl_entry( si, op, entry, &modlist,
						syncstate, &syncUUID, &syncCookie_req,
						&syncCookie.ctxcsn )) == LDAP_SUCCESS &&
						!BER_BVISNULL( &syncCookie.ctxcsn ) ) {
743
744
						syncrepl_updateCookie( si, op, psub, &syncCookie );
					}
745
				}
Howard Chu's avatar
Howard Chu committed
746
				ldap_controls_free( rctrls );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
747
				if ( modlist ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
748
					slap_mods_free( modlist, 1 );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
749
				}
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
750
751
				if ( rc )
					goto done;
752
753
754
755
				break;

			case LDAP_RES_SEARCH_REFERENCE:
				Debug( LDAP_DEBUG_ANY,
756
757
					"do_syncrep2: rid %03d reference received error\n",
					si->si_rid, 0, 0 );
758
759
760
				break;

			case LDAP_RES_SEARCH_RESULT:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
761
				Debug( LDAP_DEBUG_SYNC,
762
763
					"do_syncrep2: rid %03d LDAP_RES_SEARCH_RESULT\n",
					si->si_rid, 0, 0 );
764
				ldap_parse_result( si->si_ld, msg, &err, NULL, NULL, NULL,
765
					&rctrls, 0 );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
766
767
768
769
770
771
772
773
774
775
776
#ifdef LDAP_X_SYNC_REFRESH_REQUIRED
				if ( err == LDAP_X_SYNC_REFRESH_REQUIRED ) {
					/* map old result code to registered code */
					err = LDAP_SYNC_REFRESH_REQUIRED;
				}
#endif
				if ( err == LDAP_SYNC_REFRESH_REQUIRED ) {
					if ( si->si_logstate == SYNCLOG_LOGGING ) {
						si->si_logstate = SYNCLOG_FALLBACK;
					}
					rc = err;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
777
					goto done;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
778
				}
779
780
				if ( rctrls ) {
					rctrlp = *rctrls;
781
					ber_init2( ber, &rctrlp->ldctl_value, LBER_USE_DER );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
782

783
					ber_scanf( ber, "{" /*"}"*/);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
784
					if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE ) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
785
						ber_scanf( ber, "m", &cookie );
786
						if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
787
788
							ch_free( syncCookie.octet_str.bv_val );
							ber_dupbv( &syncCookie.octet_str, &cookie);
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
789
						}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
790
						if ( !BER_BVISNULL( &syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
791
						{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
792
							slap_parse_sync_cookie( &syncCookie, NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
793
						}
794
					}
795
796
797
798
					if ( ber_peek_tag( ber, &len ) == LDAP_TAG_REFRESHDELETES )
					{
						ber_scanf( ber, "b", &refreshDeletes );
					}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
799
					ber_scanf( ber, /*"{"*/ "}" );
800
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
801
				if ( BER_BVISNULL( &syncCookie_req.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
802
					match = -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
803
				} else if ( BER_BVISNULL( &syncCookie.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
804
805
806
807
808
					match = 1;
				} else {
					value_match( &match, slap_schema.si_ad_entryCSN,
						slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
						SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
809
						&syncCookie_req.ctxcsn, &syncCookie.ctxcsn,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
810
						&text );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
811
				}
812
813
814
815
				if ( rctrls ) {
					ldap_controls_free( rctrls );
				}
				if (si->si_type != LDAP_SYNC_REFRESH_AND_PERSIST) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
816
					/* FIXME : different error behaviors according to
817
818
819
					 *	1) err code : LDAP_BUSY ...
					 *	2) on err policy : stop service, stop sync, retry
					 */
820
					if ( refreshDeletes == 0 && match < 0 &&
Kurt Zeilenga's avatar
Kurt Zeilenga committed
821
822
						err == LDAP_SUCCESS )
					{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
823
						syncrepl_del_nonpresent( op, si, NULL, &syncCookie.ctxcsn );
824
825
826
					} else {
						avl_free( si->si_presentlist, avl_ber_bvfree );
						si->si_presentlist = NULL;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
827
					}
828
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
829
830
831
832
833
				if ( !BER_BVISNULL( &syncCookie.ctxcsn ) &&
					match < 0 && err == LDAP_SUCCESS )
				{
					syncrepl_updateCookie( si, op, psub, &syncCookie );
				}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
834
835
836
837
838
839
840
				if ( err == LDAP_SUCCESS
					&& si->si_logstate == SYNCLOG_FALLBACK ) {
					si->si_logstate = SYNCLOG_LOGGING;
					rc = LDAP_SYNC_REFRESH_REQUIRED;
				} else {
					rc = -2;
				}
841
				goto done;
842
843
				break;

844
			case LDAP_RES_INTERMEDIATE:
845
				rc = ldap_parse_intermediate( si->si_ld, msg,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
846
847
					&retoid, &retdata, NULL, 0 );
				if ( !rc && !strcmp( retoid, LDAP_SYNC_INFO ) ) {
848
					ber_init2( ber, retdata, LBER_USE_DER );
849

850
851
852
					switch ( si_tag = ber_peek_tag( ber, &len )) {
					ber_tag_t tag;
					case LDAP_TAG_SYNC_NEW_COOKIE:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
853
						Debug( LDAP_DEBUG_SYNC,
854
855
							"do_syncrep2: rid %03d %s - %s\n", 
							si->si_rid,
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
856
							"LDAP_RES_INTERMEDIATE", 
857
							"NEW_COOKIE" );
858
859
860
861
						ber_scanf( ber, "tm", &tag, &cookie );
						break;
					case LDAP_TAG_SYNC_REFRESH_DELETE:
					case LDAP_TAG_SYNC_REFRESH_PRESENT:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
862
						Debug( LDAP_DEBUG_SYNC,
863
864
							"do_syncrep2: rid %03d %s - %s\n", 
							si->si_rid,
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
865
866
							"LDAP_RES_INTERMEDIATE", 
							si_tag == LDAP_TAG_SYNC_REFRESH_PRESENT ?
867
							"REFRESH_PRESENT" : "REFRESH_DELETE" );
Howard Chu's avatar
Howard Chu committed
868
						if ( si_tag == LDAP_TAG_SYNC_REFRESH_DELETE ) {
Howard Chu's avatar
Howard Chu committed
869
870
871
872
							si->si_refreshDelete = 1;
						} else {
							si->si_refreshPresent = 1;
						}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
873
						ber_scanf( ber, "t{" /*"}"*/, &tag );
874
875
						if ( ber_peek_tag( ber, &len ) == LDAP_TAG_SYNC_COOKIE )
						{
876
							ber_scanf( ber, "m", &cookie );
877
							if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
878
879
								ch_free( syncCookie.octet_str.bv_val );
								ber_dupbv( &syncCookie.octet_str, &cookie );
880
							}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
881
							if ( !BER_BVISNULL( &syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
882
							{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
883
								slap_parse_sync_cookie( &syncCookie, NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
884
							}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
885
						}
Howard Chu's avatar
Howard Chu committed
886
						/* Defaults to TRUE */
887
						if ( ber_peek_tag( ber, &len ) ==
Kurt Zeilenga's avatar
Kurt Zeilenga committed
888
							LDAP_TAG_REFRESHDONE )
889
						{
Howard Chu's avatar
Howard Chu committed
890
891
892
893
							ber_scanf( ber, "b", &si->si_refreshDone );
						} else
						{
							si->si_refreshDone = 1;
894
						}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
895
						ber_scanf( ber, /*"{"*/ "}" );
896
897
						break;
					case LDAP_TAG_SYNC_ID_SET:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
898
						Debug( LDAP_DEBUG_SYNC,
899
900
							"do_syncrep2: rid %03d %s - %s\n", 
							si->si_rid,
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
901
							"LDAP_RES_INTERMEDIATE", 
902
							"SYNC_ID_SET" );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
903
						ber_scanf( ber, "t{" /*"}"*/, &tag );
904
						if ( ber_peek_tag( ber, &len ) ==
Kurt Zeilenga's avatar
Kurt Zeilenga committed
905
906
							LDAP_TAG_SYNC_COOKIE )
						{
907
							ber_scanf( ber, "m", &cookie );
908
							if ( !BER_BVISNULL( &cookie ) ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
909
910
								ch_free( syncCookie.octet_str.bv_val );
								ber_dupbv( &syncCookie.octet_str, &cookie );
911
							}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
912
							if ( !BER_BVISNULL( &syncCookie.octet_str ) )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
913
							{
Kurt Zeilenga's avatar
Kurt Zeilenga committed
914
								slap_parse_sync_cookie( &syncCookie, NULL );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
915
							}
916
917
						}
						if ( ber_peek_tag( ber, &len ) ==
Kurt Zeilenga's avatar
Kurt Zeilenga committed
918
							LDAP_TAG_REFRESHDELETES )
919
920
921
922
						{
							ber_scanf( ber, "b", &refreshDeletes );
						}
						ber_scanf( ber, "[W]", &syncUUIDs );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
923
						ber_scanf( ber, /*"{"*/ "}" );
924
						if ( refreshDeletes ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
925
926
							syncrepl_del_nonpresent( op, si, syncUUIDs,
								&syncCookie.ctxcsn );
927
928
929
930
931
932
933
934
935
936
937
							ber_bvarray_free_x( syncUUIDs, op->o_tmpmemctx );
						} else {
							for ( i = 0; !BER_BVISNULL( &syncUUIDs[i] ); i++ ) {
								struct berval *syncuuid_bv;
								syncuuid_bv = ber_dupbv( NULL, &syncUUIDs[i] );
								slap_sl_free( syncUUIDs[i].bv_val,op->o_tmpmemctx );
								avl_insert( &si->si_presentlist,
									(caddr_t) syncuuid_bv,
									syncuuid_cmp, avl_dup_error );
							}
							slap_sl_free( syncUUIDs, op->o_tmpmemctx );
938
						}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
939
						slap_sync_cookie_free( &syncCookie, 0 );
940
941
						break;
					default:
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
942
						Debug( LDAP_DEBUG_ANY,
943
944
							"do_syncrep2: rid %03d unknown syncinfo tag (%ld)\n",
							si->si_rid, (long) si_tag, 0 );
945
946
947
						ldap_memfree( retoid );
						ber_bvfree( retdata );
						continue;
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
948
949
					}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
950
					if ( BER_BVISNULL( &syncCookie_req.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
951
						match = -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
952
					} else if ( BER_BVISNULL( &syncCookie.ctxcsn )) {
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
953
954
955
956
957
						match = 1;
					} else {
						value_match( &match, slap_schema.si_ad_entryCSN,
							slap_schema.si_ad_entryCSN->ad_type->sat_ordering,
							SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
Kurt Zeilenga's avatar
Kurt Zeilenga committed
958
959
							&syncCookie_req.ctxcsn,
							&syncCookie.ctxcsn, &text );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
960
					}
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
961

Kurt Zeilenga's avatar
Kurt Zeilenga committed
962
963