Home | History | Annotate | Line # | Download | only in back-ldap
      1  1.3  christos /*	$NetBSD: init.c,v 1.4 2025/09/05 21:16:27 christos Exp $	*/
      2  1.2  christos 
      3  1.1     lukem /* init.c - initialize ldap backend */
      4  1.2  christos /* $OpenLDAP$ */
      5  1.1     lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  1.1     lukem  *
      7  1.4  christos  * Copyright 2003-2024 The OpenLDAP Foundation.
      8  1.1     lukem  * Portions Copyright 1999-2003 Howard Chu.
      9  1.1     lukem  * Portions Copyright 2000-2003 Pierangelo Masarati.
     10  1.1     lukem  * All rights reserved.
     11  1.1     lukem  *
     12  1.1     lukem  * Redistribution and use in source and binary forms, with or without
     13  1.1     lukem  * modification, are permitted only as authorized by the OpenLDAP
     14  1.1     lukem  * Public License.
     15  1.1     lukem  *
     16  1.1     lukem  * A copy of this license is available in the file LICENSE in the
     17  1.1     lukem  * top-level directory of the distribution or, alternatively, at
     18  1.1     lukem  * <http://www.OpenLDAP.org/license.html>.
     19  1.1     lukem  */
     20  1.1     lukem /* ACKNOWLEDGEMENTS:
     21  1.1     lukem  * This work was initially developed by the Howard Chu for inclusion
     22  1.1     lukem  * in OpenLDAP Software and subsequently enhanced by Pierangelo
     23  1.1     lukem  * Masarati.
     24  1.1     lukem  */
     25  1.1     lukem 
     26  1.2  christos #include <sys/cdefs.h>
     27  1.3  christos __RCSID("$NetBSD: init.c,v 1.4 2025/09/05 21:16:27 christos Exp $");
     28  1.2  christos 
     29  1.1     lukem #include "portable.h"
     30  1.1     lukem 
     31  1.1     lukem #include <stdio.h>
     32  1.1     lukem 
     33  1.1     lukem #include <ac/string.h>
     34  1.1     lukem #include <ac/socket.h>
     35  1.1     lukem 
     36  1.1     lukem #include "slap.h"
     37  1.3  christos #include "slap-config.h"
     38  1.1     lukem #include "back-ldap.h"
     39  1.3  christos #include "ldap_rq.h"
     40  1.1     lukem 
     41  1.1     lukem static const ldap_extra_t ldap_extra = {
     42  1.1     lukem 	ldap_back_proxy_authz_ctrl,
     43  1.2  christos 	ldap_back_controls_free,
     44  1.2  christos 	slap_idassert_authzfrom_parse,
     45  1.2  christos 	slap_idassert_passthru_parse_cf,
     46  1.2  christos 	slap_idassert_parse,
     47  1.2  christos 	slap_retry_info_destroy,
     48  1.2  christos 	slap_retry_info_parse,
     49  1.2  christos 	slap_retry_info_unparse,
     50  1.2  christos 	ldap_back_connid2str
     51  1.1     lukem };
     52  1.1     lukem 
     53  1.1     lukem int
     54  1.1     lukem ldap_back_open( BackendInfo	*bi )
     55  1.1     lukem {
     56  1.1     lukem 	bi->bi_controls = slap_known_controls;
     57  1.1     lukem 	return 0;
     58  1.1     lukem }
     59  1.1     lukem 
     60  1.1     lukem int
     61  1.1     lukem ldap_back_initialize( BackendInfo *bi )
     62  1.1     lukem {
     63  1.1     lukem 	int		rc;
     64  1.1     lukem 
     65  1.1     lukem 	bi->bi_flags =
     66  1.1     lukem #ifdef LDAP_DYNAMIC_OBJECTS
     67  1.1     lukem 		/* this is set because all the support a proxy has to provide
     68  1.1     lukem 		 * is the capability to forward the refresh exop, and to
     69  1.1     lukem 		 * pass thru entries that contain the dynamicObject class
     70  1.1     lukem 		 * and the entryTtl attribute */
     71  1.1     lukem 		SLAP_BFLAG_DYNAMIC |
     72  1.1     lukem #endif /* LDAP_DYNAMIC_OBJECTS */
     73  1.2  christos 
     74  1.2  christos 		/* back-ldap recognizes RFC4525 increment;
     75  1.2  christos 		 * let the remote server complain, if needed (ITS#5912) */
     76  1.2  christos 		SLAP_BFLAG_INCREMENT;
     77  1.1     lukem 
     78  1.1     lukem 	bi->bi_open = ldap_back_open;
     79  1.1     lukem 	bi->bi_config = 0;
     80  1.1     lukem 	bi->bi_close = 0;
     81  1.1     lukem 	bi->bi_destroy = 0;
     82  1.1     lukem 
     83  1.1     lukem 	bi->bi_db_init = ldap_back_db_init;
     84  1.1     lukem 	bi->bi_db_config = config_generic_wrapper;
     85  1.1     lukem 	bi->bi_db_open = ldap_back_db_open;
     86  1.1     lukem 	bi->bi_db_close = ldap_back_db_close;
     87  1.1     lukem 	bi->bi_db_destroy = ldap_back_db_destroy;
     88  1.1     lukem 
     89  1.1     lukem 	bi->bi_op_bind = ldap_back_bind;
     90  1.1     lukem 	bi->bi_op_unbind = 0;
     91  1.1     lukem 	bi->bi_op_search = ldap_back_search;
     92  1.1     lukem 	bi->bi_op_compare = ldap_back_compare;
     93  1.1     lukem 	bi->bi_op_modify = ldap_back_modify;
     94  1.1     lukem 	bi->bi_op_modrdn = ldap_back_modrdn;
     95  1.1     lukem 	bi->bi_op_add = ldap_back_add;
     96  1.1     lukem 	bi->bi_op_delete = ldap_back_delete;
     97  1.1     lukem 	bi->bi_op_abandon = 0;
     98  1.1     lukem 
     99  1.1     lukem 	bi->bi_extended = ldap_back_extended;
    100  1.1     lukem 
    101  1.1     lukem 	bi->bi_chk_referrals = 0;
    102  1.1     lukem 	bi->bi_entry_get_rw = ldap_back_entry_get;
    103  1.1     lukem 
    104  1.1     lukem 	bi->bi_connection_init = 0;
    105  1.1     lukem 	bi->bi_connection_destroy = ldap_back_conn_destroy;
    106  1.1     lukem 
    107  1.1     lukem 	bi->bi_extra = (void *)&ldap_extra;
    108  1.1     lukem 
    109  1.2  christos 	rc =  ldap_back_init_cf( bi );
    110  1.2  christos 	if ( rc ) {
    111  1.2  christos 		return rc;
    112  1.2  christos 	}
    113  1.2  christos 
    114  1.1     lukem 	rc = chain_initialize();
    115  1.1     lukem 	if ( rc ) {
    116  1.1     lukem 		return rc;
    117  1.1     lukem 	}
    118  1.1     lukem 
    119  1.2  christos 	rc = pbind_initialize();
    120  1.2  christos 	if ( rc ) {
    121  1.2  christos 		return rc;
    122  1.2  christos 	}
    123  1.2  christos 
    124  1.1     lukem #ifdef SLAP_DISTPROC
    125  1.1     lukem 	rc = distproc_initialize();
    126  1.1     lukem 	if ( rc ) {
    127  1.1     lukem 		return rc;
    128  1.1     lukem 	}
    129  1.1     lukem #endif
    130  1.2  christos 	return rc;
    131  1.1     lukem }
    132  1.1     lukem 
    133  1.1     lukem int
    134  1.1     lukem ldap_back_db_init( Backend *be, ConfigReply *cr )
    135  1.1     lukem {
    136  1.1     lukem 	ldapinfo_t	*li;
    137  1.1     lukem 	int		rc;
    138  1.1     lukem 	unsigned	i;
    139  1.1     lukem 
    140  1.1     lukem 	li = (ldapinfo_t *)ch_calloc( 1, sizeof( ldapinfo_t ) );
    141  1.1     lukem 	if ( li == NULL ) {
    142  1.1     lukem  		return -1;
    143  1.1     lukem  	}
    144  1.1     lukem 
    145  1.1     lukem 	li->li_rebind_f = ldap_back_default_rebind;
    146  1.1     lukem 	li->li_urllist_f = ldap_back_default_urllist;
    147  1.1     lukem 	li->li_urllist_p = li;
    148  1.1     lukem 	ldap_pvt_thread_mutex_init( &li->li_uri_mutex );
    149  1.1     lukem 
    150  1.1     lukem 	BER_BVZERO( &li->li_acl_authcID );
    151  1.1     lukem 	BER_BVZERO( &li->li_acl_authcDN );
    152  1.1     lukem 	BER_BVZERO( &li->li_acl_passwd );
    153  1.1     lukem 
    154  1.1     lukem 	li->li_acl_authmethod = LDAP_AUTH_NONE;
    155  1.1     lukem 	BER_BVZERO( &li->li_acl_sasl_mech );
    156  1.1     lukem 	li->li_acl.sb_tls = SB_TLS_DEFAULT;
    157  1.1     lukem 
    158  1.1     lukem 	li->li_idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
    159  1.1     lukem 
    160  1.1     lukem 	BER_BVZERO( &li->li_idassert_authcID );
    161  1.1     lukem 	BER_BVZERO( &li->li_idassert_authcDN );
    162  1.1     lukem 	BER_BVZERO( &li->li_idassert_passwd );
    163  1.1     lukem 
    164  1.1     lukem 	BER_BVZERO( &li->li_idassert_authzID );
    165  1.1     lukem 
    166  1.1     lukem 	li->li_idassert_authmethod = LDAP_AUTH_NONE;
    167  1.1     lukem 	BER_BVZERO( &li->li_idassert_sasl_mech );
    168  1.1     lukem 	li->li_idassert_tls = SB_TLS_DEFAULT;
    169  1.1     lukem 
    170  1.1     lukem 	/* by default, use proxyAuthz control on each operation */
    171  1.1     lukem 	li->li_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE;
    172  1.1     lukem 
    173  1.1     lukem 	li->li_idassert_authz = NULL;
    174  1.1     lukem 
    175  1.1     lukem 	/* initialize flags */
    176  1.1     lukem 	li->li_flags = LDAP_BACK_F_CHASE_REFERRALS;
    177  1.1     lukem 
    178  1.1     lukem 	/* initialize version */
    179  1.1     lukem 	li->li_version = LDAP_VERSION3;
    180  1.1     lukem 
    181  1.1     lukem 	ldap_pvt_thread_mutex_init( &li->li_conninfo.lai_mutex );
    182  1.1     lukem 
    183  1.1     lukem 	for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
    184  1.1     lukem 		li->li_conn_priv[ i ].lic_num = 0;
    185  1.1     lukem 		LDAP_TAILQ_INIT( &li->li_conn_priv[ i ].lic_priv );
    186  1.1     lukem 	}
    187  1.1     lukem 	li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_DEFAULT;
    188  1.1     lukem 
    189  1.2  christos 	ldap_pvt_thread_mutex_init( &li->li_counter_mutex );
    190  1.2  christos 	for ( i = 0; i < SLAP_OP_LAST; i++ ) {
    191  1.2  christos 		ldap_pvt_mp_init( li->li_ops_completed[ i ] );
    192  1.2  christos 	}
    193  1.2  christos 
    194  1.3  christos 	li->li_conn_expire_task = NULL;
    195  1.3  christos 
    196  1.1     lukem 	be->be_private = li;
    197  1.1     lukem 	SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_NOLASTMOD;
    198  1.1     lukem 
    199  1.1     lukem 	be->be_cf_ocs = be->bd_info->bi_cf_ocs;
    200  1.1     lukem 
    201  1.1     lukem 	rc = ldap_back_monitor_db_init( be );
    202  1.1     lukem 	if ( rc != 0 ) {
    203  1.1     lukem 		/* ignore, by now */
    204  1.1     lukem 		rc = 0;
    205  1.1     lukem 	}
    206  1.1     lukem 
    207  1.1     lukem 	return rc;
    208  1.1     lukem }
    209  1.1     lukem 
    210  1.1     lukem int
    211  1.1     lukem ldap_back_db_open( BackendDB *be, ConfigReply *cr )
    212  1.1     lukem {
    213  1.1     lukem 	ldapinfo_t	*li = (ldapinfo_t *)be->be_private;
    214  1.1     lukem 
    215  1.1     lukem 	slap_bindconf	sb = { BER_BVNULL };
    216  1.1     lukem 	int		rc = 0;
    217  1.1     lukem 
    218  1.1     lukem 	Debug( LDAP_DEBUG_TRACE,
    219  1.1     lukem 		"ldap_back_db_open: URI=%s\n",
    220  1.3  christos 		li->li_uri != NULL ? li->li_uri : "" );
    221  1.1     lukem 
    222  1.1     lukem 	/* by default, use proxyAuthz control on each operation */
    223  1.1     lukem 	switch ( li->li_idassert_mode ) {
    224  1.1     lukem 	case LDAP_BACK_IDASSERT_LEGACY:
    225  1.1     lukem 	case LDAP_BACK_IDASSERT_SELF:
    226  1.1     lukem 		/* however, since admin connections are pooled and shared,
    227  1.1     lukem 		 * only static authzIDs can be native */
    228  1.1     lukem 		li->li_idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
    229  1.1     lukem 		break;
    230  1.1     lukem 
    231  1.1     lukem 	default:
    232  1.1     lukem 		break;
    233  1.1     lukem 	}
    234  1.1     lukem 
    235  1.1     lukem 	ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri );
    236  1.1     lukem 	sb.sb_version = li->li_version;
    237  1.1     lukem 	sb.sb_method = LDAP_AUTH_SIMPLE;
    238  1.1     lukem 	BER_BVSTR( &sb.sb_binddn, "" );
    239  1.1     lukem 
    240  1.1     lukem 	if ( LDAP_BACK_T_F_DISCOVER( li ) && !LDAP_BACK_T_F( li ) ) {
    241  1.1     lukem 		rc = slap_discover_feature( &sb,
    242  1.1     lukem 				slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
    243  1.1     lukem 				LDAP_FEATURE_ABSOLUTE_FILTERS );
    244  1.1     lukem 		if ( rc == LDAP_COMPARE_TRUE ) {
    245  1.1     lukem 			li->li_flags |= LDAP_BACK_F_T_F;
    246  1.1     lukem 		}
    247  1.1     lukem 	}
    248  1.1     lukem 
    249  1.1     lukem 	if ( LDAP_BACK_CANCEL_DISCOVER( li ) && !LDAP_BACK_CANCEL( li ) ) {
    250  1.1     lukem 		rc = slap_discover_feature( &sb,
    251  1.1     lukem 				slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
    252  1.1     lukem 				LDAP_EXOP_CANCEL );
    253  1.1     lukem 		if ( rc == LDAP_COMPARE_TRUE ) {
    254  1.1     lukem 			li->li_flags |= LDAP_BACK_F_CANCEL_EXOP;
    255  1.1     lukem 		}
    256  1.1     lukem 	}
    257  1.1     lukem 
    258  1.1     lukem 	/* monitor setup */
    259  1.1     lukem 	rc = ldap_back_monitor_db_open( be );
    260  1.1     lukem 	if ( rc != 0 ) {
    261  1.1     lukem 		/* ignore by now */
    262  1.1     lukem 		rc = 0;
    263  1.1     lukem 	}
    264  1.1     lukem 
    265  1.1     lukem 	li->li_flags |= LDAP_BACK_F_ISOPEN;
    266  1.1     lukem 
    267  1.1     lukem 	return rc;
    268  1.1     lukem }
    269  1.1     lukem 
    270  1.1     lukem void
    271  1.1     lukem ldap_back_conn_free( void *v_lc )
    272  1.1     lukem {
    273  1.1     lukem 	ldapconn_t	*lc = v_lc;
    274  1.1     lukem 
    275  1.1     lukem 	if ( lc->lc_ld != NULL ) {
    276  1.1     lukem 		ldap_unbind_ext( lc->lc_ld, NULL, NULL );
    277  1.1     lukem 	}
    278  1.1     lukem 	if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
    279  1.1     lukem 		ch_free( lc->lc_bound_ndn.bv_val );
    280  1.1     lukem 	}
    281  1.1     lukem 	if ( !BER_BVISNULL( &lc->lc_cred ) ) {
    282  1.1     lukem 		memset( lc->lc_cred.bv_val, 0, lc->lc_cred.bv_len );
    283  1.1     lukem 		ch_free( lc->lc_cred.bv_val );
    284  1.1     lukem 	}
    285  1.1     lukem 	if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
    286  1.1     lukem 		ch_free( lc->lc_local_ndn.bv_val );
    287  1.1     lukem 	}
    288  1.1     lukem 	lc->lc_q.tqe_prev = NULL;
    289  1.1     lukem 	lc->lc_q.tqe_next = NULL;
    290  1.1     lukem 	ch_free( lc );
    291  1.1     lukem }
    292  1.1     lukem 
    293  1.1     lukem int
    294  1.1     lukem ldap_back_db_close( Backend *be, ConfigReply *cr )
    295  1.1     lukem {
    296  1.1     lukem 	int		rc = 0;
    297  1.1     lukem 
    298  1.1     lukem 	if ( be->be_private ) {
    299  1.1     lukem 		rc = ldap_back_monitor_db_close( be );
    300  1.1     lukem 	}
    301  1.1     lukem 
    302  1.1     lukem 	return rc;
    303  1.1     lukem }
    304  1.1     lukem 
    305  1.1     lukem int
    306  1.1     lukem ldap_back_db_destroy( Backend *be, ConfigReply *cr )
    307  1.1     lukem {
    308  1.1     lukem 	if ( be->be_private ) {
    309  1.1     lukem 		ldapinfo_t	*li = ( ldapinfo_t * )be->be_private;
    310  1.1     lukem 		unsigned	i;
    311  1.1     lukem 
    312  1.1     lukem 		(void)ldap_back_monitor_db_destroy( be );
    313  1.1     lukem 
    314  1.3  christos 		/* Stop and remove the task that prunes expired connections */
    315  1.3  christos 		if ( li->li_conn_expire_task != NULL ) {
    316  1.3  christos 			ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
    317  1.3  christos 			if ( ldap_pvt_runqueue_isrunning( &slapd_rq, li->li_conn_expire_task ) ) {
    318  1.3  christos 					ldap_pvt_runqueue_stoptask( &slapd_rq, li->li_conn_expire_task );
    319  1.3  christos 			}
    320  1.3  christos 			ldap_pvt_runqueue_remove( &slapd_rq, li->li_conn_expire_task );
    321  1.3  christos 			ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
    322  1.3  christos 		}
    323  1.3  christos 
    324  1.1     lukem 		ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
    325  1.1     lukem 
    326  1.1     lukem 		if ( li->li_uri != NULL ) {
    327  1.1     lukem 			ch_free( li->li_uri );
    328  1.1     lukem 			li->li_uri = NULL;
    329  1.1     lukem 
    330  1.1     lukem 			assert( li->li_bvuri != NULL );
    331  1.1     lukem 			ber_bvarray_free( li->li_bvuri );
    332  1.1     lukem 			li->li_bvuri = NULL;
    333  1.1     lukem 		}
    334  1.2  christos 
    335  1.2  christos 		bindconf_free( &li->li_tls );
    336  1.2  christos 		bindconf_free( &li->li_acl );
    337  1.2  christos 		bindconf_free( &li->li_idassert.si_bc );
    338  1.2  christos 
    339  1.1     lukem 		if ( li->li_idassert_authz != NULL ) {
    340  1.1     lukem 			ber_bvarray_free( li->li_idassert_authz );
    341  1.1     lukem 			li->li_idassert_authz = NULL;
    342  1.1     lukem 		}
    343  1.1     lukem                	if ( li->li_conninfo.lai_tree ) {
    344  1.3  christos 			ldap_tavl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
    345  1.1     lukem 		}
    346  1.1     lukem 		for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
    347  1.1     lukem 			while ( !LDAP_TAILQ_EMPTY( &li->li_conn_priv[ i ].lic_priv ) ) {
    348  1.1     lukem 				ldapconn_t	*lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ i ].lic_priv );
    349  1.1     lukem 
    350  1.1     lukem 				LDAP_TAILQ_REMOVE( &li->li_conn_priv[ i ].lic_priv, lc, lc_q );
    351  1.1     lukem 				ldap_back_conn_free( lc );
    352  1.1     lukem 			}
    353  1.1     lukem 		}
    354  1.1     lukem 		if ( LDAP_BACK_QUARANTINE( li ) ) {
    355  1.1     lukem 			slap_retry_info_destroy( &li->li_quarantine );
    356  1.1     lukem 			ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
    357  1.1     lukem 		}
    358  1.1     lukem 
    359  1.1     lukem 		ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
    360  1.1     lukem 		ldap_pvt_thread_mutex_destroy( &li->li_conninfo.lai_mutex );
    361  1.1     lukem 		ldap_pvt_thread_mutex_destroy( &li->li_uri_mutex );
    362  1.2  christos 
    363  1.2  christos 		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
    364  1.2  christos 			ldap_pvt_mp_clear( li->li_ops_completed[ i ] );
    365  1.2  christos 		}
    366  1.2  christos 		ldap_pvt_thread_mutex_destroy( &li->li_counter_mutex );
    367  1.1     lukem 	}
    368  1.1     lukem 
    369  1.1     lukem 	ch_free( be->be_private );
    370  1.1     lukem 
    371  1.1     lukem 	return 0;
    372  1.1     lukem }
    373  1.1     lukem 
    374  1.1     lukem #if SLAPD_LDAP == SLAPD_MOD_DYNAMIC
    375  1.1     lukem 
    376  1.1     lukem /* conditionally define the init_module() function */
    377  1.1     lukem SLAP_BACKEND_INIT_MODULE( ldap )
    378  1.1     lukem 
    379  1.1     lukem #endif /* SLAPD_LDAP == SLAPD_MOD_DYNAMIC */
    380