backend.c 44.1 KB
Newer Older
Kurt Zeilenga's avatar
Kurt Zeilenga committed
1
/* backend.c - routines for dealing with back-end databases */
2
/* $OpenLDAP$ */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
5
 * Copyright 1998-2020 The OpenLDAP Foundation.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * 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>.
 */
/* Portions Copyright (c) 1995 Regents of the University of Michigan.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of Michigan at Ann Arbor. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
Kurt Zeilenga's avatar
Kurt Zeilenga committed
25
 */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
26
27


Kurt Zeilenga's avatar
Kurt Zeilenga committed
28
29
#include "portable.h"

Kurt Zeilenga's avatar
Kurt Zeilenga committed
30
#include <stdio.h>
Pierangelo Masarati's avatar
Pierangelo Masarati committed
31

Kurt Zeilenga's avatar
Kurt Zeilenga committed
32
33
#include <ac/string.h>
#include <ac/socket.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
34
#include <sys/stat.h>
Kurt Zeilenga's avatar
Kurt Zeilenga committed
35

Kurt Zeilenga's avatar
Kurt Zeilenga committed
36
#include "slap.h"
37
#include "config.h"
38
#include "lutil.h"
39
#include "lber_pvt.h"
Kurt Zeilenga's avatar
Kurt Zeilenga committed
40

41
42
43
44
45
46
47
48
/*
 * If a module is configured as dynamic, its header should not
 * get included into slapd. While this is a general rule and does
 * not have much of an effect in UNIX, this rule should be adhered
 * to for Windows, where dynamic object code should not be implicitly
 * imported into slapd without appropriate __declspec(dllimport) directives.
 */

49
int			nBackendInfo = 0;
50
slap_bi_head backendInfo = LDAP_STAILQ_HEAD_INITIALIZER(backendInfo);
Kurt Zeilenga's avatar
Kurt Zeilenga committed
51

52
int			nBackendDB = 0; 
53
slap_be_head backendDB = LDAP_STAILQ_HEAD_INITIALIZER(backendDB);
54

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
static int
backend_init_controls( BackendInfo *bi )
{
	if ( bi->bi_controls ) {
		int	i;

		for ( i = 0; bi->bi_controls[ i ]; i++ ) {
			int	cid;

			if ( slap_find_control_id( bi->bi_controls[ i ], &cid )
					== LDAP_CONTROL_NOT_FOUND )
			{
				if ( !( slapMode & SLAP_TOOL_MODE ) ) {
					assert( 0 );
				}

				return -1;
			}

			bi->bi_ctrls[ cid ] = 1;
		}
	}

	return 0;
}

81
82
extern int syncrepl_monitor_init(void);

83
int backend_init(void)
Kurt Zeilenga's avatar
Kurt Zeilenga committed
84
{
85
	int rc = -1;
86
	BackendInfo *bi;
87

88
	if((nBackendInfo != 0) || !LDAP_STAILQ_EMPTY(&backendInfo)) {
89
90
		/* already initialized */
		Debug( LDAP_DEBUG_ANY,
91
			"backend_init: already initialized\n" );
92
		return -1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
93
94
	}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
95
	for( bi=slap_binfo; bi->bi_type != NULL; bi++,nBackendInfo++ ) {
96
		assert( bi->bi_init != 0 );
97

98
		rc = bi->bi_init( bi );
99
100
101
102

		if(rc != 0) {
			Debug( LDAP_DEBUG_ANY,
				"backend_init: initialized for type \"%s\"\n",
103
				bi->bi_type );
104
105
106
107
108
			/* destroy those we've already inited */
			for( nBackendInfo--;
				nBackendInfo >= 0 ;
				nBackendInfo-- )
			{ 
109
110
111
				if ( slap_binfo[nBackendInfo].bi_destroy ) {
					slap_binfo[nBackendInfo].bi_destroy(
						&slap_binfo[nBackendInfo] );
112
113
114
115
				}
			}
			return rc;
		}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
116

117
		LDAP_STAILQ_INSERT_TAIL(&backendInfo, bi, bi_next);
118
	}
119
120
	/* HACK: need schema defined in deterministic order */
	syncrepl_monitor_init();
Kurt Zeilenga's avatar
Kurt Zeilenga committed
121

122
123
	if ( nBackendInfo > 0) {
		return 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
124
125
	}

126
127
128
#ifdef SLAPD_MODULES	
	return 0;
#else
129

130
	Debug( LDAP_DEBUG_ANY,
131
		"backend_init: failed\n" );
132

133
	return rc;
134
135
136
137
138
#endif /* SLAPD_MODULES */
}

int backend_add(BackendInfo *aBackendInfo)
{
139
	int rc = 0;
140

141
142
143
	if ( aBackendInfo->bi_init == NULL ) {
		Debug( LDAP_DEBUG_ANY, "backend_add: "
			"backend type \"%s\" does not have the (mandatory)init function\n",
144
			aBackendInfo->bi_type );
145
146
		return -1;
	}
147

148
149
	rc = aBackendInfo->bi_init(aBackendInfo);
	if ( rc != 0) {
150
151
		Debug( LDAP_DEBUG_ANY,
			"backend_add:  initialization for type \"%s\" failed\n",
152
			aBackendInfo->bi_type );
153
		return rc;
154
155
156
	}

	(void)backend_init_controls( aBackendInfo );
157

158
	/* now add the backend type to the Backend Info List */
159
160
161
	LDAP_STAILQ_INSERT_TAIL( &backendInfo, aBackendInfo, bi_next );
	nBackendInfo++;
	return 0;
162
163
}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
164
165
static int
backend_set_controls( BackendDB *be )
Howard Chu's avatar
Howard Chu committed
166
{
167
	BackendInfo	*bi = be->bd_info;
Howard Chu's avatar
Howard Chu committed
168

169
	/* back-relay takes care of itself; so may do other */
170
171
172
	if ( overlay_is_over( be ) ) {
		bi = ((slap_overinfo *)be->bd_info->bi_private)->oi_orig;
	}
173

174
	if ( bi->bi_controls ) {
175
		if ( be->be_ctrls[ SLAP_MAX_CIDS ] == 0 ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
176
177
			AC_MEMCPY( be->be_ctrls, bi->bi_ctrls,
					sizeof( be->be_ctrls ) );
178
			be->be_ctrls[ SLAP_MAX_CIDS ] = 1;
179
			
180
181
		} else {
			int	i;
182
			
183
184
			for ( i = 0; i < SLAP_MAX_CIDS; i++ ) {
				if ( bi->bi_ctrls[ i ] ) {
Pierangelo Masarati's avatar
Pierangelo Masarati committed
185
					be->be_ctrls[ i ] = bi->bi_ctrls[ i ];
186
187
				}
			}
188
		}
189

190
191
	}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
192
193
194
195
	return 0;
}

/* startup a specific backend database */
196
int backend_startup_one(Backend *be, ConfigReply *cr)
Pierangelo Masarati's avatar
Pierangelo Masarati committed
197
198
199
{
	int		rc = 0;

200
	assert( be != NULL );
201

Pierangelo Masarati's avatar
Pierangelo Masarati committed
202
	be->be_pending_csn_list = (struct be_pcl *)
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
203
		ch_calloc( 1, sizeof( struct be_pcl ) );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
204
205
206
207
208

	LDAP_TAILQ_INIT( be->be_pending_csn_list );

	Debug( LDAP_DEBUG_TRACE,
		"backend_startup_one: starting \"%s\"\n",
209
		be->be_suffix ? be->be_suffix[0].bv_val : "(unknown)" );
210
211

	/* set database controls */
Pierangelo Masarati's avatar
Pierangelo Masarati committed
212
	(void)backend_set_controls( be );
213

214
215
216
217
218
219
220
221
222
223
224
#if 0
	if ( !BER_BVISEMPTY( &be->be_rootndn )
		&& select_backend( &be->be_rootndn, 0 ) == be
		&& BER_BVISNULL( &be->be_rootpw ) )
	{
		/* warning: if rootdn entry is created,
		 * it can take rootdn privileges;
		 * set empty rootpw to prevent */
	}
#endif

Pierangelo Masarati's avatar
Pierangelo Masarati committed
225
	if ( be->bd_info->bi_db_open ) {
226
		rc = be->bd_info->bi_db_open( be, cr );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
227
228
229
230
		if ( rc == 0 ) {
			(void)backend_set_controls( be );

		} else {
231
232
233
234
235
236
237
238
239
240
241
242
			char *type = be->bd_info->bi_type;
			char *suffix = "(null)";

			if ( overlay_is_over( be ) ) {
				slap_overinfo	*oi = (slap_overinfo *)be->bd_info->bi_private;
				type = oi->oi_orig->bi_type;
			}

			if ( be->be_suffix != NULL && !BER_BVISNULL( &be->be_suffix[0] ) ) {
				suffix = be->be_suffix[0].bv_val;
			}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
243
			Debug( LDAP_DEBUG_ANY,
244
245
246
				"backend_startup_one (type=%s, suffix=\"%s\"): "
				"bi_db_open failed! (%d)\n",
				type, suffix, rc );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
247
248
249
		}
	}

Howard Chu's avatar
Howard Chu committed
250
251
252
	return rc;
}

253
int backend_startup(Backend *be)
254
255
256
{
	int i;
	int rc = 0;
257
	BackendInfo *bi;
258
	ConfigReply cr={0, ""};
259
260
261
262
263

	if( ! ( nBackendDB > 0 ) ) {
		/* no databases */
		Debug( LDAP_DEBUG_ANY,
			"backend_startup: %d databases to startup.\n",
264
			nBackendDB );
265
		return 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
266
267
	}

268
	if(be != NULL) {
269
270
271
		/* silent noop if disabled */
		if ( SLAP_DBDISABLED( be ))
			return 0;
272
273
		if ( be->bd_info->bi_open ) {
			rc = be->bd_info->bi_open( be->bd_info );
274
275
			if ( rc != 0 ) {
				Debug( LDAP_DEBUG_ANY,
276
					"backend_startup: bi_open failed!\n" );
277

278
279
				return rc;
			}
280
281
		}

282
		return backend_startup_one( be, &cr );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
283
284
	}

285
286
	/* open frontend, if required */
	if ( frontendDB->bd_info->bi_db_open ) {
287
		rc = frontendDB->bd_info->bi_db_open( frontendDB, &cr );
288
289
290
		if ( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"backend_startup: bi_db_open(frontend) failed! (%d)\n",
291
				rc );
292
293
294
295
			return rc;
		}
	}

296
	/* open each backend type */
297
298
299
300
	i = -1;
	LDAP_STAILQ_FOREACH(bi, &backendInfo, bi_next) {
		i++;
		if( bi->bi_nDB == 0) {
301
302
303
304
			/* no database of this type, don't open */
			continue;
		}

305
306
		if( bi->bi_open ) {
			rc = bi->bi_open( bi );
307
308
			if ( rc != 0 ) {
				Debug( LDAP_DEBUG_ANY,
309
					"backend_startup: bi_open %d (%s) failed!\n",
310
					i, bi->bi_type );
311
312
				return rc;
			}
313
		}
314

315
		(void)backend_init_controls( bi );
316
317
	}

318
	/* open each backend database */
319
320
321
	i = -1;
	LDAP_STAILQ_FOREACH(be, &backendDB, be_next) {
		i++;
322
323
		if ( SLAP_DBDISABLED( be ))
			continue;
324
		if ( be->be_suffix == NULL ) {
325
326
327
			Debug( LDAP_DEBUG_ANY,
				"backend_startup: warning, database %d (%s) "
				"has no suffix\n",
328
				i, be->bd_info->bi_type );
329
		}
Howard Chu's avatar
Howard Chu committed
330

331
		rc = backend_startup_one( be, &cr );
Howard Chu's avatar
Howard Chu committed
332
333

		if ( rc ) return rc;
334
335
336
337
338
	}

	return rc;
}

339
int backend_num( Backend *be )
340
{
341
342
	int i = 0;
	BackendDB *b2;
343

344
345
	if( be == NULL ) return -1;

346
347
348
	LDAP_STAILQ_FOREACH( b2, &backendDB, be_next ) {
		if( be == b2 ) return i;
		i++;
349
350
351
	}
	return -1;
}
352

353
354
355
int backend_shutdown( Backend *be )
{
	int rc = 0;
356
	BackendInfo *bi;
357

358
359
	if( be != NULL ) {
		/* shutdown a specific backend database */
360

361
		if ( be->bd_info->bi_nDB == 0 ) {
362
363
364
365
			/* no database of this type, we never opened it */
			return 0;
		}

366
		if ( be->bd_info->bi_db_close ) {
367
368
			rc = be->bd_info->bi_db_close( be, NULL );
			if ( rc ) return rc;
369
370
		}

371
		if( be->bd_info->bi_close ) {
372
373
			rc = be->bd_info->bi_close( be->bd_info );
			if ( rc ) return rc;
374
375
376
377
378
379
		}

		return 0;
	}

	/* close each backend database */
380
	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
381
382
		if ( SLAP_DBDISABLED( be ))
			continue;
383
		if ( be->bd_info->bi_db_close ) {
384
			be->bd_info->bi_db_close( be, NULL );
385
		}
386
387
388

		if(rc != 0) {
			Debug( LDAP_DEBUG_ANY,
389
				"backend_close: bi_db_close %s failed!\n",
390
				be->be_type );
391
		}
392
393
394
	}

	/* close each backend type */
395
396
	LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) {
		if( bi->bi_nDB == 0 ) {
397
398
399
400
			/* no database of this type */
			continue;
		}

401
402
		if( bi->bi_close ) {
			bi->bi_close( bi );
403
404
405
		}
	}

406
407
	/* close frontend, if required */
	if ( frontendDB->bd_info->bi_db_close ) {
408
		rc = frontendDB->bd_info->bi_db_close ( frontendDB, NULL );
409
410
411
		if ( rc != 0 ) {
			Debug( LDAP_DEBUG_ANY,
				"backend_startup: bi_db_close(frontend) failed! (%d)\n",
412
				rc );
413
414
415
		}
	}

416
417
418
	return 0;
}

419
420
421
422
423
424
425
426
427
428
429
/*
 * This function is supposed to be the exact counterpart
 * of backend_startup_one(), although this one calls bi_db_destroy()
 * while backend_startup_one() calls bi_db_open().
 *
 * Make sure backend_stopdown_one() destroys resources allocated
 * by backend_startup_one(); only call backend_destroy_one() when
 * all stuff in a BackendDB needs to be destroyed
 */
void
backend_stopdown_one( BackendDB *bd )
430
431
432
433
434
435
436
437
438
439
440
441
{
	if ( bd->be_pending_csn_list ) {
		struct slap_csn_entry *csne;
		csne = LDAP_TAILQ_FIRST( bd->be_pending_csn_list );
		while ( csne ) {
			struct slap_csn_entry *tmp_csne = csne;

			LDAP_TAILQ_REMOVE( bd->be_pending_csn_list, csne, ce_csn_link );
			ch_free( csne->ce_csn.bv_val );
			csne = LDAP_TAILQ_NEXT( csne, ce_csn_link );
			ch_free( tmp_csne );
		}
Howard Chu's avatar
Howard Chu committed
442
		ch_free( bd->be_pending_csn_list );
443
444
445
	}

	if ( bd->bd_info->bi_db_destroy ) {
446
		bd->bd_info->bi_db_destroy( bd, NULL );
447
	}
448
449
450
451
452
}

void backend_destroy_one( BackendDB *bd, int dynamic )
{
	if ( dynamic ) {
453
		LDAP_STAILQ_REMOVE(&backendDB, bd, BackendDB, be_next );
454
455
456
	}

	if ( bd->be_syncinfo ) {
457
		syncinfo_free( bd->be_syncinfo, 1 );
458
459
460
461
	}

	backend_stopdown_one( bd );

462
463
464
465
466
467
468
469
470
471
472
	ber_bvarray_free( bd->be_suffix );
	ber_bvarray_free( bd->be_nsuffix );
	if ( !BER_BVISNULL( &bd->be_rootdn ) ) {
		free( bd->be_rootdn.bv_val );
	}
	if ( !BER_BVISNULL( &bd->be_rootndn ) ) {
		free( bd->be_rootndn.bv_val );
	}
	if ( !BER_BVISNULL( &bd->be_rootpw ) ) {
		free( bd->be_rootpw.bv_val );
	}
Howard Chu's avatar
Howard Chu committed
473
	acl_destroy( bd->be_acl );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
474
	limits_destroy( bd->be_limits );
475
476
477
	if ( bd->be_extra_anlist ) {
		anlist_free( bd->be_extra_anlist, 1, NULL );
	}
478
479
480
481
482
483
	if ( !BER_BVISNULL( &bd->be_update_ndn ) ) {
		ch_free( bd->be_update_ndn.bv_val );
	}
	if ( bd->be_update_refs ) {
		ber_bvarray_free( bd->be_update_refs );
	}
484

485
486
	ldap_pvt_thread_mutex_destroy( &bd->be_pcl_mutex );

Howard Chu's avatar
Howard Chu committed
487
488
489
	if ( dynamic ) {
		free( bd );
	}
490
491
}

492
493
int backend_destroy(void)
{
Howard Chu's avatar
Howard Chu committed
494
	BackendDB *bd;
495
	BackendInfo *bi;
496
497

	/* destroy each backend database */
498
	while (( bd = LDAP_STAILQ_FIRST(&backendDB))) {
Howard Chu's avatar
Howard Chu committed
499
		backend_destroy_one( bd, 1 );
500
	}
501

502
	/* destroy each backend type */
503
504
505
	LDAP_STAILQ_FOREACH( bi, &backendInfo, bi_next ) {
		if( bi->bi_destroy ) {
			bi->bi_destroy( bi );
506
507
508
		}
	}

509
	nBackendInfo = 0;
510
	LDAP_STAILQ_INIT(&backendInfo);
511

512
513
	/* destroy frontend database */
	bd = frontendDB;
514
515
	if ( bd ) {
		if ( bd->bd_info->bi_db_destroy ) {
516
			bd->bd_info->bi_db_destroy( bd, NULL );
517
518
519
		}
		ber_bvarray_free( bd->be_suffix );
		ber_bvarray_free( bd->be_nsuffix );
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
520
521
522
523
524
525
526
527
528
		if ( !BER_BVISNULL( &bd->be_rootdn ) ) {
			free( bd->be_rootdn.bv_val );
		}
		if ( !BER_BVISNULL( &bd->be_rootndn ) ) {
			free( bd->be_rootndn.bv_val );
		}
		if ( !BER_BVISNULL( &bd->be_rootpw ) ) {
			free( bd->be_rootpw.bv_val );
		}
Howard Chu's avatar
Howard Chu committed
529
530
		acl_destroy( bd->be_acl );
		frontendDB = NULL;
531
532
	}

533
534
535
	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
536
BackendInfo* backend_info(const char *type)
537
{
538
	BackendInfo *bi;
539

540
	/* search for the backend type */
541
542
543
	LDAP_STAILQ_FOREACH(bi,&backendInfo,bi_next) {
		if( strcasecmp(bi->bi_type, type) == 0 ) {
			return bi;
544
		}
Kurt Zeilenga's avatar
Kurt Zeilenga committed
545
546
	}

547
548
549
	return NULL;
}

550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
void
backend_db_insert(
	BackendDB *be,
	int idx
)
{
	/* If idx < 0, just add to end of list */
	if ( idx < 0 ) {
		LDAP_STAILQ_INSERT_TAIL(&backendDB, be, be_next);
	} else if ( idx == 0 ) {
		LDAP_STAILQ_INSERT_HEAD(&backendDB, be, be_next);
	} else {
		int i;
		BackendDB *b2;

		b2 = LDAP_STAILQ_FIRST(&backendDB);
		idx--;
		for (i=0; i<idx; i++) {
			b2 = LDAP_STAILQ_NEXT(b2, be_next);
		}
		LDAP_STAILQ_INSERT_AFTER(&backendDB, b2, be, be_next);
	}
}

void
backend_db_move(
	BackendDB *be,
	int idx
)
{
580
	LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
581
582
	backend_db_insert(be, idx);
}
583
584
585

BackendDB *
backend_db_init(
586
    const char	*type,
587
	BackendDB *b0,
588
	int idx,
589
	ConfigReply *cr)
590
591
{
	BackendInfo *bi = backend_info(type);
592
	BackendDB *be = b0;
593
594
595
	int	rc = 0;

	if( bi == NULL ) {
Kurt Zeilenga's avatar
Kurt Zeilenga committed
596
		fprintf( stderr, "Unrecognized database type (%s)\n", type );
597
598
599
		return NULL;
	}

600
601
602
603
604
	/* If be is provided, treat it as private. Otherwise allocate
	 * one and add it to the global list.
	 */
	if ( !be ) {
		be = ch_calloc( 1, sizeof(Backend) );
605
606
607
		/* Just append */
		if ( idx >= nbackends )
			idx = -1;
608
		nbackends++;
609
		backend_db_insert( be, idx );
610
	}
611
612

	be->bd_info = bi;
613
	be->bd_self = be;
614

615
616
	be->be_def_limit = frontendDB->be_def_limit;
	be->be_dfltaccess = frontendDB->be_dfltaccess;
617

618
619
620
	be->be_restrictops = frontendDB->be_restrictops;
	be->be_requires = frontendDB->be_requires;
	be->be_ssf_set = frontendDB->be_ssf_set;
621

622
	ldap_pvt_thread_mutex_init( &be->be_pcl_mutex );
Jong Hyuk Choi's avatar
Jong Hyuk Choi committed
623

Kurt Zeilenga's avatar
Kurt Zeilenga committed
624
625
626
 	/* assign a default depth limit for alias deref */
	be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; 

627
	if ( bi->bi_db_init ) {
628
		rc = bi->bi_db_init( be, cr );
629
630
	}

631
	if ( rc != 0 ) {
632
		fprintf( stderr, "database init failed (%s)\n", type );
633
634
		/* If we created and linked this be, remove it and free it */
		if ( !b0 ) {
635
			LDAP_STAILQ_REMOVE(&backendDB, be, BackendDB, be_next);
636
			ldap_pvt_thread_mutex_destroy( &be->be_pcl_mutex );
637
638
639
640
641
			ch_free( be );
			be = NULL;
			nbackends--;
		}
	} else {
642
643
644
		if ( !bi->bi_nDB ) {
			backend_init_controls( bi );
		}
645
		bi->bi_nDB++;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
646
647
648
649
	}
	return( be );
}

650
651
652
void
be_db_close( void )
{
653
	BackendDB *be;
654

655
656
	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
		if ( be->bd_info->bi_db_close ) {
657
			be->bd_info->bi_db_close( be, NULL );
658
659
		}
	}
660
661

	if ( frontendDB->bd_info->bi_db_close ) {
662
		frontendDB->bd_info->bi_db_close( frontendDB, NULL );
663
	}
664

665
666
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
667
Backend *
668
select_backend(
669
	struct berval * dn,
670
	int noSubs )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
671
{
Howard Chu's avatar
Howard Chu committed
672
	int		j;
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
673
	ber_len_t	len, dnlen = dn->bv_len;
674
	Backend		*be;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
675

676
	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
677
		if ( be->be_nsuffix == NULL || SLAP_DBHIDDEN( be ) || SLAP_DBDISABLED( be )) {
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
678
679
680
			continue;
		}

681
		for ( j = 0; !BER_BVISNULL( &be->be_nsuffix[j] ); j++ )
682
		{
683
			if ( ( SLAP_GLUE_SUBORDINATE( be ) ) && noSubs )
684
			{
685
			  	continue;
686
			}
687

688
			len = be->be_nsuffix[j].bv_len;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
689
690

			if ( len > dnlen ) {
691
				/* suffix is longer than DN */
Kurt Zeilenga's avatar
Kurt Zeilenga committed
692
693
				continue;
			}
694
			
695
696
697
698
			/*
			 * input DN is normalized, so the separator check
			 * need not look at escaping
			 */
699
			if ( len && len < dnlen &&
700
				!DN_SEPARATOR( dn->bv_val[(dnlen-len)-1] ))
701
			{
702
703
704
				continue;
			}

705
			if ( strcmp( be->be_nsuffix[j].bv_val,
706
707
				&dn->bv_val[dnlen-len] ) == 0 )
			{
Howard Chu's avatar
Howard Chu committed
708
				return be;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
709
710
711
712
			}
		}
	}

713
	return be;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
714
715
716
717
}

int
be_issuffix(
718
719
    Backend *be,
    struct berval *bvsuffix )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
720
721
722
{
	int	i;

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
723
724
725
726
727
	if ( be->be_nsuffix == NULL ) {
		return 0;
	}

	for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
728
		if ( bvmatch( &be->be_nsuffix[i], bvsuffix ) ) {
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
729
			return 1;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
730
731
732
		}
	}

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
733
	return 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
734
735
}

736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
int
be_issubordinate(
    Backend *be,
    struct berval *bvsubordinate )
{
	int	i;

	if ( be->be_nsuffix == NULL ) {
		return 0;
	}

	for ( i = 0; !BER_BVISNULL( &be->be_nsuffix[i] ); i++ ) {
		if ( dnIsSuffix( bvsubordinate, &be->be_nsuffix[i] ) ) {
			return 1;
		}
	}

	return 0;
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
756
int
757
be_isroot_dn( Backend *be, struct berval *ndn )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
758
{
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
759
760
	if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_rootndn ) ) {
		return 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
761
762
	}

763
	return dn_match( &be->be_rootndn, ndn );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
764
765
}

766
767
768
int
be_slurp_update( Operation *op )
{
769
	return ( SLAP_SLURP_SHADOW( op->o_bd ) &&
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
770
		be_isupdate_dn( op->o_bd, &op->o_ndn ) );
771
772
773
774
775
}

int
be_shadow_update( Operation *op )
{
776
	/* This assumes that all internal ops (connid <= -1000) on a syncrepl
777
778
	 * database are syncrepl operations.
	 */
779
	return ( ( SLAP_SYNC_SHADOW( op->o_bd ) && SLAPD_SYNC_IS_SYNCCONN( op->o_connid ) ) ||
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
780
		( SLAP_SHADOW( op->o_bd ) && be_isupdate_dn( op->o_bd, &op->o_ndn ) ) );
781
782
783
784
}

int
be_isupdate_dn( Backend *be, struct berval *ndn )
Pierangelo Masarati's avatar
Pierangelo Masarati committed
785
{
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
786
787
788
	if ( BER_BVISEMPTY( ndn ) || BER_BVISEMPTY( &be->be_update_ndn ) ) {
		return 0;
	}
Pierangelo Masarati's avatar
Pierangelo Masarati committed
789

790
	return dn_match( &be->be_update_ndn, ndn );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
791
792
}

793
struct berval *
794
795
be_root_dn( Backend *be )
{
796
	return &be->be_rootdn;
797
798
}

Pierangelo Masarati's avatar
Pierangelo Masarati committed
799
int
800
be_isroot( Operation *op )
Pierangelo Masarati's avatar
Pierangelo Masarati committed
801
{
802
	return be_isroot_dn( op->o_bd, &op->o_ndn );
Pierangelo Masarati's avatar
Pierangelo Masarati committed
803
804
}

Kurt Zeilenga's avatar
Kurt Zeilenga committed
805
int
806
be_isroot_pw( Operation *op )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
807
{
808
809
	return be_rootdn_bind( op, NULL ) == LDAP_SUCCESS;
}
810

811
812
813
814
/*
 * checks if binding as rootdn
 *
 * return value:
815
 *	SLAP_CB_CONTINUE		if not the rootdn, or if rootpw is null
816
817
818
819
820
821
822
823
824
825
826
 *	LDAP_SUCCESS			if rootdn & rootpw
 *	LDAP_INVALID_CREDENTIALS	if rootdn & !rootpw
 *
 * if rs != NULL
 *	if LDAP_SUCCESS, op->orb_edn is set
 *	if LDAP_INVALID_CREDENTIALS, response is sent to client
 */
int
be_rootdn_bind( Operation *op, SlapReply *rs )
{
	int		rc;
827
828
829
#ifdef SLAPD_SPASSWD
	void	*old_authctx = NULL;
#endif
830
831
832
833
834
835

	assert( op->o_tag == LDAP_REQ_BIND );
	assert( op->orb_method == LDAP_AUTH_SIMPLE );

	if ( !be_isroot_dn( op->o_bd, &op->o_req_ndn ) ) {
		return SLAP_CB_CONTINUE;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
836
837
	}

838
839
840
841
842
	if ( BER_BVISNULL( &op->o_bd->be_rootpw ) ) {
		/* give the database a chance */
		return SLAP_CB_CONTINUE;
	}

Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
843
	if ( BER_BVISEMPTY( &op->o_bd->be_rootpw ) ) {
844
		/* rootdn bind explicitly disallowed */
845
846
847
848
849
850
		rc = LDAP_INVALID_CREDENTIALS;
		if ( rs ) {
			goto send_result;
		}

		return rc;
851
852
	}

853
#ifdef SLAPD_SPASSWD
854
855
	ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind,
		op->o_conn->c_sasl_authctx, 0, &old_authctx, NULL );
856
857
#endif

858
	rc = lutil_passwd( &op->o_bd->be_rootpw, &op->orb_cred, NULL, NULL );
859

Kurt Zeilenga's avatar
Kurt Zeilenga committed
860
#ifdef SLAPD_SPASSWD
861
862
	ldap_pvt_thread_pool_setkey( op->o_threadctx, (void *)slap_sasl_bind,
		old_authctx, 0, NULL, NULL );
863
864
#endif

865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
	rc = ( rc == 0 ? LDAP_SUCCESS : LDAP_INVALID_CREDENTIALS );
	if ( rs ) {
send_result:;
		rs->sr_err = rc;

		Debug( LDAP_DEBUG_TRACE, "%s: rootdn=\"%s\" bind%s\n", 
			op->o_log_prefix, op->o_bd->be_rootdn.bv_val,
			rc == LDAP_SUCCESS ? " succeeded" : " failed" );

		if ( rc == LDAP_SUCCESS ) {
			/* Set to the pretty rootdn */
     			ber_dupbv( &op->orb_edn, &op->o_bd->be_rootdn );

		} else {
			send_ldap_result( op, rs );
		}
	}

	return rc;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
884
885
}

886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
/* Inlined in proto-slap.h, sans assertions, when !(USE_RS_ASSERT) */
int
(slap_bi_op)(
	BackendInfo *bi,
	slap_operation_t which,
	Operation *op,
	SlapReply *rs )
{
	int rc;
#ifndef slap_bi_op
	void (*rsCheck)( const SlapReply *rs ) =
		which < op_aux_operational ? rs_assert_ready : rs_assert_ok;
#else
#	define rsCheck(rs) ((void) 0)
#endif
	BI_op_func *fn;

	assert( bi != NULL );
	assert( (unsigned) which < (unsigned) op_last );

	fn = (&bi->bi_op_bind)[ which ];

	assert( op != NULL );
	assert( rs != NULL );
	assert( fn != 0 );
	rsCheck( rs );

	rc = fn( op, rs );

#ifndef slap_bi_op
	if ( rc != SLAP_CB_CONTINUE && rc != SLAP_CB_BYPASS ) {
		int err = rs->sr_err;

		if ( 0 )	/* TODO */
		if ( err == LDAP_COMPARE_TRUE || err == LDAP_COMPARE_FALSE ) {
			assert( which == op_compare );
			assert( rc == LDAP_SUCCESS );
		}

		rsCheck = which < op_extended ? rs_assert_done : rs_assert_ok;
		if ( which == op_aux_chk_referrals ) {
			if      ( rc == LDAP_SUCCESS  ) rsCheck = rs_assert_ready;
			else if ( rc == LDAP_REFERRAL ) rsCheck = rs_assert_done;
		} else if ( which == op_bind ) {
			if      ( rc == LDAP_SUCCESS  ) rsCheck = rs_assert_ok;
		}

		/* TODO: Just what is the relation between rc and rs->sr_err? */
		if ( rc != err &&
			(rc != LDAP_SUCCESS ||
			 (err != LDAP_COMPARE_TRUE && err != LDAP_COMPARE_FALSE)) )
		{
			rs->sr_err = rc;
			rsCheck( rs );
			rs->sr_err = err;
		}
	}
	rsCheck( rs );
#endif

	return rc;
}

949
int
950
951
952
953
be_entry_release_rw(
	Operation *op,
	Entry *e,
	int rw )
954
{
955
	if ( op->o_bd->be_release ) {
956
		/* free and release entry from backend */
957
		return op->o_bd->be_release( op, e, rw );
958
959
960
961
962
963
964
	} else {
		/* free entry */
		entry_free( e );
		return 0;
	}
}

965
int
966
backend_unbind( Operation *op, SlapReply *rs )
Kurt Zeilenga's avatar
Kurt Zeilenga committed
967
{
968
	BackendDB *be;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
969

970
971
972
973
	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
		if ( be->be_unbind ) {
			op->o_bd = be;
			be->be_unbind( op, rs );
Kurt Zeilenga's avatar
Kurt Zeilenga committed
974
975
		}
	}
976
977

	return 0;
Kurt Zeilenga's avatar
Kurt Zeilenga committed
978
}
979

980
981
int
backend_connection_init(
982
	Connection   *conn )
983
{
984
	BackendDB *be;
985

986
987
	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
		if ( be->be_connection_init ) {
Pierangelo Masarati's avatar
cleanup    
Pierangelo Masarati committed
988
			be->be_connection_init( be, conn );
989
990
991
992
993
994
995
996
		}
	}

	return 0;
}

int
backend_connection_destroy(
997
	Connection   *conn )
998
{
999
	BackendDB *be;
1000

1001
1002
1003
	LDAP_STAILQ_FOREACH( be, &backendDB, be_next ) {
		if ( be->be_connection_destroy ) {
			be->be_connection_destroy( be, conn);
1004
1005
1006
1007
1008
1009
		}
	}

	return 0;
}

1010
int
1011
backend_check_controls(
1012
	Operation *op,
1013
	SlapReply *rs )
1014
{
1015
	LDAPControl **ctrls = op->o_ctrls;
1016
	rs->sr_err = LDAP_SUCCESS;
1017

1018
1019
	if( ctrls ) {
		for( ; *ctrls != NULL ; ctrls++ ) {