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