xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-meta/init.c (revision c2f76ff004a2cb67efe5b12d97bd3ef7fe89e18d)
1 /*	$NetBSD: init.c,v 1.1.1.4 2010/12/12 15:23:11 adam Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/servers/slapd/back-meta/init.c,v 1.58.2.14 2010/04/13 20:23:31 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2010 The OpenLDAP Foundation.
7  * Portions Copyright 2001-2003 Pierangelo Masarati.
8  * Portions Copyright 1999-2003 Howard Chu.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 
20 #include "portable.h"
21 
22 #include <stdio.h>
23 
24 #include <ac/string.h>
25 #include <ac/socket.h>
26 
27 #include "slap.h"
28 #include "config.h"
29 #include "../back-ldap/back-ldap.h"
30 #include "back-meta.h"
31 
32 int
33 meta_back_open(
34 	BackendInfo	*bi )
35 {
36 	/* FIXME: need to remove the pagedResults, and likely more... */
37 	bi->bi_controls = slap_known_controls;
38 
39 	return 0;
40 }
41 
42 int
43 meta_back_initialize(
44 	BackendInfo	*bi )
45 {
46 	bi->bi_flags =
47 #if 0
48 	/* this is not (yet) set essentially because back-meta does not
49 	 * directly support extended operations... */
50 #ifdef LDAP_DYNAMIC_OBJECTS
51 		/* this is set because all the support a proxy has to provide
52 		 * is the capability to forward the refresh exop, and to
53 		 * pass thru entries that contain the dynamicObject class
54 		 * and the entryTtl attribute */
55 		SLAP_BFLAG_DYNAMIC |
56 #endif /* LDAP_DYNAMIC_OBJECTS */
57 #endif
58 
59 		/* back-meta recognizes RFC4525 increment;
60 		 * let the remote server complain, if needed (ITS#5912) */
61 		SLAP_BFLAG_INCREMENT;
62 
63 	bi->bi_open = meta_back_open;
64 	bi->bi_config = 0;
65 	bi->bi_close = 0;
66 	bi->bi_destroy = 0;
67 
68 	bi->bi_db_init = meta_back_db_init;
69 	bi->bi_db_config = meta_back_db_config;
70 	bi->bi_db_open = meta_back_db_open;
71 	bi->bi_db_close = 0;
72 	bi->bi_db_destroy = meta_back_db_destroy;
73 
74 	bi->bi_op_bind = meta_back_bind;
75 	bi->bi_op_unbind = 0;
76 	bi->bi_op_search = meta_back_search;
77 	bi->bi_op_compare = meta_back_compare;
78 	bi->bi_op_modify = meta_back_modify;
79 	bi->bi_op_modrdn = meta_back_modrdn;
80 	bi->bi_op_add = meta_back_add;
81 	bi->bi_op_delete = meta_back_delete;
82 	bi->bi_op_abandon = 0;
83 
84 	bi->bi_extended = 0;
85 
86 	bi->bi_chk_referrals = 0;
87 
88 	bi->bi_connection_init = 0;
89 	bi->bi_connection_destroy = meta_back_conn_destroy;
90 
91 	return 0;
92 }
93 
94 int
95 meta_back_db_init(
96 	Backend		*be,
97 	ConfigReply	*cr)
98 {
99 	metainfo_t	*mi;
100 	int		i;
101 	BackendInfo	*bi;
102 
103 	bi = backend_info( "ldap" );
104 	if ( !bi || !bi->bi_extra ) {
105 		Debug( LDAP_DEBUG_ANY,
106 			"meta_back_db_init: needs back-ldap\n",
107 			0, 0, 0 );
108 		return 1;
109 	}
110 
111 	mi = ch_calloc( 1, sizeof( metainfo_t ) );
112 	if ( mi == NULL ) {
113  		return -1;
114  	}
115 
116 	/* set default flags */
117 	mi->mi_flags =
118 		META_BACK_F_DEFER_ROOTDN_BIND;
119 
120 	/*
121 	 * At present the default is no default target;
122 	 * this may change
123 	 */
124 	mi->mi_defaulttarget = META_DEFAULT_TARGET_NONE;
125 	mi->mi_bind_timeout.tv_sec = 0;
126 	mi->mi_bind_timeout.tv_usec = META_BIND_TIMEOUT;
127 
128 	mi->mi_rebind_f = meta_back_default_rebind;
129 	mi->mi_urllist_f = meta_back_default_urllist;
130 
131 	ldap_pvt_thread_mutex_init( &mi->mi_conninfo.lai_mutex );
132 	ldap_pvt_thread_mutex_init( &mi->mi_cache.mutex );
133 
134 	/* safe default */
135 	mi->mi_nretries = META_RETRY_DEFAULT;
136 	mi->mi_version = LDAP_VERSION3;
137 
138 	for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
139 		mi->mi_conn_priv[ i ].mic_num = 0;
140 		LDAP_TAILQ_INIT( &mi->mi_conn_priv[ i ].mic_priv );
141 	}
142 	mi->mi_conn_priv_max = LDAP_BACK_CONN_PRIV_DEFAULT;
143 
144 	mi->mi_ldap_extra = (ldap_extra_t *)bi->bi_extra;
145 
146 	be->be_private = mi;
147 
148 	return 0;
149 }
150 
151 int
152 meta_back_db_open(
153 	Backend		*be,
154 	ConfigReply	*cr )
155 {
156 	metainfo_t	*mi = (metainfo_t *)be->be_private;
157 
158 	int		i,
159 			not_always = 0,
160 			not_always_anon_proxyauthz = 0,
161 			not_always_anon_non_prescriptive = 0,
162 			rc;
163 
164 	if ( mi->mi_ntargets == 0 ) {
165 		Debug( LDAP_DEBUG_ANY,
166 			"meta_back_db_open: no targets defined\n",
167 			0, 0, 0 );
168 		return 1;
169 	}
170 
171 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
172 		slap_bindconf	sb = { BER_BVNULL };
173 		metatarget_t	*mt = mi->mi_targets[ i ];
174 
175 		struct berval mapped;
176 
177 		ber_str2bv( mt->mt_uri, 0, 0, &sb.sb_uri );
178 		sb.sb_version = mt->mt_version;
179 		sb.sb_method = LDAP_AUTH_SIMPLE;
180 		BER_BVSTR( &sb.sb_binddn, "" );
181 
182 		if ( META_BACK_TGT_T_F_DISCOVER( mt ) ) {
183 			rc = slap_discover_feature( &sb,
184 					slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
185 					LDAP_FEATURE_ABSOLUTE_FILTERS );
186 			if ( rc == LDAP_COMPARE_TRUE ) {
187 				mt->mt_flags |= LDAP_BACK_F_T_F;
188 			}
189 		}
190 
191 		if ( META_BACK_TGT_CANCEL_DISCOVER( mt ) ) {
192 			rc = slap_discover_feature( &sb,
193 					slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
194 					LDAP_EXOP_CANCEL );
195 			if ( rc == LDAP_COMPARE_TRUE ) {
196 				mt->mt_flags |= LDAP_BACK_F_CANCEL_EXOP;
197 			}
198 		}
199 
200 		if ( not_always == 0 ) {
201 			if ( !( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE )
202 				|| mt->mt_idassert_authz != NULL )
203 			{
204 				not_always = 1;
205 			}
206 		}
207 
208 		if ( ( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL )
209 			&& !( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) )
210 		{
211 			Debug( LDAP_DEBUG_ANY, "meta_back_db_open(%s): "
212 				"target #%d inconsistent idassert configuration "
213 				"(likely authz=\"*\" used with \"non-prescriptive\" flag)\n",
214 				be->be_suffix[ 0 ].bv_val, i, 0 );
215 			return 1;
216 		}
217 
218 		if ( not_always_anon_proxyauthz == 0 ) {
219 			if ( !( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) )
220 			{
221 				not_always_anon_proxyauthz = 1;
222 			}
223 		}
224 
225 		if ( not_always_anon_non_prescriptive == 0 ) {
226 			if ( ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) )
227 			{
228 				not_always_anon_non_prescriptive = 1;
229 			}
230 		}
231 
232 		BER_BVZERO( &mapped );
233 		ldap_back_map( &mt->mt_rwmap.rwm_at,
234 			&slap_schema.si_ad_entryDN->ad_cname, &mapped,
235 			BACKLDAP_REMAP );
236 		if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
237 			mt->mt_rep_flags |= REP_NO_ENTRYDN;
238 		}
239 
240 		BER_BVZERO( &mapped );
241 		ldap_back_map( &mt->mt_rwmap.rwm_at,
242 			&slap_schema.si_ad_subschemaSubentry->ad_cname, &mapped,
243 			BACKLDAP_REMAP );
244 		if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
245 			mt->mt_rep_flags |= REP_NO_SUBSCHEMA;
246 		}
247 	}
248 
249 	if ( not_always == 0 ) {
250 		mi->mi_flags |= META_BACK_F_PROXYAUTHZ_ALWAYS;
251 	}
252 
253 	if ( not_always_anon_proxyauthz == 0 ) {
254 		mi->mi_flags |= META_BACK_F_PROXYAUTHZ_ANON;
255 
256 	} else if ( not_always_anon_non_prescriptive == 0 ) {
257 		mi->mi_flags |= META_BACK_F_PROXYAUTHZ_NOANON;
258 	}
259 
260 	return 0;
261 }
262 
263 /*
264  * meta_back_conn_free()
265  *
266  * actually frees a connection; the reference count must be 0,
267  * and it must not (or no longer) be in the cache.
268  */
269 void
270 meta_back_conn_free(
271 	void 		*v_mc )
272 {
273 	metaconn_t		*mc = v_mc;
274 	int			ntargets;
275 
276 	assert( mc != NULL );
277 	assert( mc->mc_refcnt == 0 );
278 
279 	/* at least one must be present... */
280 	ntargets = mc->mc_info->mi_ntargets;
281 	assert( ntargets > 0 );
282 
283 	for ( ; ntargets--; ) {
284 		(void)meta_clear_one_candidate( NULL, mc, ntargets );
285 	}
286 
287 	if ( !BER_BVISNULL( &mc->mc_local_ndn ) ) {
288 		free( mc->mc_local_ndn.bv_val );
289 	}
290 
291 	free( mc );
292 }
293 
294 static void
295 mapping_free(
296 	void		*v_mapping )
297 {
298 	struct ldapmapping *mapping = v_mapping;
299 	ch_free( mapping->src.bv_val );
300 	ch_free( mapping->dst.bv_val );
301 	ch_free( mapping );
302 }
303 
304 static void
305 mapping_dst_free(
306 	void		*v_mapping )
307 {
308 	struct ldapmapping *mapping = v_mapping;
309 
310 	if ( BER_BVISEMPTY( &mapping->dst ) ) {
311 		mapping_free( &mapping[ -1 ] );
312 	}
313 }
314 
315 static void
316 target_free(
317 	metatarget_t	*mt )
318 {
319 	if ( mt->mt_uri ) {
320 		free( mt->mt_uri );
321 		ldap_pvt_thread_mutex_destroy( &mt->mt_uri_mutex );
322 	}
323 	if ( mt->mt_subtree_exclude ) {
324 		ber_bvarray_free( mt->mt_subtree_exclude );
325 	}
326 	if ( !BER_BVISNULL( &mt->mt_psuffix ) ) {
327 		free( mt->mt_psuffix.bv_val );
328 	}
329 	if ( !BER_BVISNULL( &mt->mt_nsuffix ) ) {
330 		free( mt->mt_nsuffix.bv_val );
331 	}
332 	if ( !BER_BVISNULL( &mt->mt_binddn ) ) {
333 		free( mt->mt_binddn.bv_val );
334 	}
335 	if ( !BER_BVISNULL( &mt->mt_bindpw ) ) {
336 		free( mt->mt_bindpw.bv_val );
337 	}
338 	if ( !BER_BVISNULL( &mt->mt_idassert_authcID ) ) {
339 		ch_free( mt->mt_idassert_authcID.bv_val );
340 	}
341 	if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) ) {
342 		ch_free( mt->mt_idassert_authcDN.bv_val );
343 	}
344 	if ( !BER_BVISNULL( &mt->mt_idassert_passwd ) ) {
345 		ch_free( mt->mt_idassert_passwd.bv_val );
346 	}
347 	if ( !BER_BVISNULL( &mt->mt_idassert_authzID ) ) {
348 		ch_free( mt->mt_idassert_authzID.bv_val );
349 	}
350 	if ( !BER_BVISNULL( &mt->mt_idassert_sasl_mech ) ) {
351 		ch_free( mt->mt_idassert_sasl_mech.bv_val );
352 	}
353 	if ( !BER_BVISNULL( &mt->mt_idassert_sasl_realm ) ) {
354 		ch_free( mt->mt_idassert_sasl_realm.bv_val );
355 	}
356 	if ( mt->mt_idassert_authz != NULL ) {
357 		ber_bvarray_free( mt->mt_idassert_authz );
358 	}
359 	if ( mt->mt_rwmap.rwm_rw ) {
360 		rewrite_info_delete( &mt->mt_rwmap.rwm_rw );
361 	}
362 	avl_free( mt->mt_rwmap.rwm_oc.remap, mapping_dst_free );
363 	avl_free( mt->mt_rwmap.rwm_oc.map, mapping_free );
364 	avl_free( mt->mt_rwmap.rwm_at.remap, mapping_dst_free );
365 	avl_free( mt->mt_rwmap.rwm_at.map, mapping_free );
366 
367 	free( mt );
368 }
369 
370 int
371 meta_back_db_destroy(
372 	Backend		*be,
373 	ConfigReply	*cr )
374 {
375 	metainfo_t	*mi;
376 
377 	if ( be->be_private ) {
378 		int i;
379 
380 		mi = ( metainfo_t * )be->be_private;
381 
382 		/*
383 		 * Destroy the connection tree
384 		 */
385 		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
386 
387 		if ( mi->mi_conninfo.lai_tree ) {
388 			avl_free( mi->mi_conninfo.lai_tree, meta_back_conn_free );
389 		}
390 		for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
391 			while ( !LDAP_TAILQ_EMPTY( &mi->mi_conn_priv[ i ].mic_priv ) ) {
392 				metaconn_t	*mc = LDAP_TAILQ_FIRST( &mi->mi_conn_priv[ i ].mic_priv );
393 
394 				LDAP_TAILQ_REMOVE( &mi->mi_conn_priv[ i ].mic_priv, mc, mc_q );
395 				meta_back_conn_free( mc );
396 			}
397 		}
398 
399 		/*
400 		 * Destroy the per-target stuff (assuming there's at
401 		 * least one ...)
402 		 */
403 		if ( mi->mi_targets != NULL ) {
404 			for ( i = 0; i < mi->mi_ntargets; i++ ) {
405 				metatarget_t	*mt = mi->mi_targets[ i ];
406 
407 				if ( META_BACK_TGT_QUARANTINE( mt ) ) {
408 					if ( mt->mt_quarantine.ri_num != mi->mi_quarantine.ri_num )
409 					{
410 						mi->mi_ldap_extra->retry_info_destroy( &mt->mt_quarantine );
411 					}
412 
413 					ldap_pvt_thread_mutex_destroy( &mt->mt_quarantine_mutex );
414 				}
415 
416 				target_free( mt );
417 			}
418 
419 			free( mi->mi_targets );
420 		}
421 
422 		ldap_pvt_thread_mutex_lock( &mi->mi_cache.mutex );
423 		if ( mi->mi_cache.tree ) {
424 			avl_free( mi->mi_cache.tree, meta_dncache_free );
425 		}
426 
427 		ldap_pvt_thread_mutex_unlock( &mi->mi_cache.mutex );
428 		ldap_pvt_thread_mutex_destroy( &mi->mi_cache.mutex );
429 
430 		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
431 		ldap_pvt_thread_mutex_destroy( &mi->mi_conninfo.lai_mutex );
432 
433 		if ( mi->mi_candidates != NULL ) {
434 			ber_memfree_x( mi->mi_candidates, NULL );
435 		}
436 
437 		if ( META_BACK_QUARANTINE( mi ) ) {
438 			mi->mi_ldap_extra->retry_info_destroy( &mi->mi_quarantine );
439 		}
440 	}
441 
442 	free( be->be_private );
443 	return 0;
444 }
445 
446 #if SLAPD_META == SLAPD_MOD_DYNAMIC
447 
448 /* conditionally define the init_module() function */
449 SLAP_BACKEND_INIT_MODULE( meta )
450 
451 #endif /* SLAPD_META == SLAPD_MOD_DYNAMIC */
452 
453 
454