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