143412Snewton/*	$NetBSD: init.c,v 1.3 2021/08/14 16:14:59 christos Exp $	*/
243412Snewton
343412Snewton/* init.c - initialize ldap backend */
443412Snewton/* $OpenLDAP$ */
543412Snewton/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
643412Snewton *
743412Snewton * Copyright 2003-2021 The OpenLDAP Foundation.
843412Snewton * Portions Copyright 1999-2003 Howard Chu.
943412Snewton * Portions Copyright 2000-2003 Pierangelo Masarati.
1043412Snewton * All rights reserved.
1143412Snewton *
1243412Snewton * Redistribution and use in source and binary forms, with or without
1343412Snewton * modification, are permitted only as authorized by the OpenLDAP
1443412Snewton * Public License.
1543412Snewton *
1643412Snewton * A copy of this license is available in the file LICENSE in the
1743412Snewton * top-level directory of the distribution or, alternatively, at
1843412Snewton * <http://www.OpenLDAP.org/license.html>.
1943412Snewton */
2043412Snewton/* ACKNOWLEDGEMENTS:
2143412Snewton * This work was initially developed by the Howard Chu for inclusion
2243412Snewton * in OpenLDAP Software and subsequently enhanced by Pierangelo
2343412Snewton * Masarati.
2443412Snewton */
2543412Snewton
2643412Snewton#include <sys/cdefs.h>
2743412Snewton__RCSID("$NetBSD: init.c,v 1.3 2021/08/14 16:14:59 christos Exp $");
2843412Snewton
2949267Snewton#include "portable.h"
3050477Speter
3143412Snewton#include <stdio.h>
3243412Snewton
3343412Snewton#include <ac/string.h>
3443412Snewton#include <ac/socket.h>
3543412Snewton
3643412Snewton#include "slap.h"
3743412Snewton#include "slap-config.h"
3843412Snewton#include "back-ldap.h"
3943412Snewton#include "ldap_rq.h"
4043412Snewton
4143412Snewtonstatic const ldap_extra_t ldap_extra = {
4243412Snewton	ldap_back_proxy_authz_ctrl,
4343412Snewton	ldap_back_controls_free,
4443412Snewton	slap_idassert_authzfrom_parse,
4543412Snewton	slap_idassert_passthru_parse_cf,
4643412Snewton	slap_idassert_parse,
4743412Snewton	slap_retry_info_destroy,
4843412Snewton	slap_retry_info_parse,
4943412Snewton	slap_retry_info_unparse,
5043412Snewton	ldap_back_connid2str
5143412Snewton};
5243412Snewton
5343412Snewtonint
5443412Snewtonldap_back_open( BackendInfo	*bi )
5543412Snewton{
5643412Snewton	bi->bi_controls = slap_known_controls;
5743412Snewton	return 0;
5843412Snewton}
5943412Snewton
6043412Snewtonint
6143412Snewtonldap_back_initialize( BackendInfo *bi )
6243412Snewton{
6343412Snewton	int		rc;
6443412Snewton
6543412Snewton	bi->bi_flags =
6643412Snewton#ifdef LDAP_DYNAMIC_OBJECTS
6743412Snewton		/* this is set because all the support a proxy has to provide
6843412Snewton		 * is the capability to forward the refresh exop, and to
6943412Snewton		 * pass thru entries that contain the dynamicObject class
7043412Snewton		 * and the entryTtl attribute */
7143412Snewton		SLAP_BFLAG_DYNAMIC |
7243412Snewton#endif /* LDAP_DYNAMIC_OBJECTS */
7343412Snewton
7443412Snewton		/* back-ldap recognizes RFC4525 increment;
7543412Snewton		 * let the remote server complain, if needed (ITS#5912) */
7643412Snewton		SLAP_BFLAG_INCREMENT;
7743412Snewton
7843412Snewton	bi->bi_open = ldap_back_open;
7943412Snewton	bi->bi_config = 0;
8043412Snewton	bi->bi_close = 0;
8143412Snewton	bi->bi_destroy = 0;
8243412Snewton
8343412Snewton	bi->bi_db_init = ldap_back_db_init;
8443412Snewton	bi->bi_db_config = config_generic_wrapper;
8543412Snewton	bi->bi_db_open = ldap_back_db_open;
8643412Snewton	bi->bi_db_close = ldap_back_db_close;
8743412Snewton	bi->bi_db_destroy = ldap_back_db_destroy;
8843412Snewton
8943412Snewton	bi->bi_op_bind = ldap_back_bind;
9043412Snewton	bi->bi_op_unbind = 0;
9143412Snewton	bi->bi_op_search = ldap_back_search;
9243412Snewton	bi->bi_op_compare = ldap_back_compare;
9343412Snewton	bi->bi_op_modify = ldap_back_modify;
9443412Snewton	bi->bi_op_modrdn = ldap_back_modrdn;
9543412Snewton	bi->bi_op_add = ldap_back_add;
9643412Snewton	bi->bi_op_delete = ldap_back_delete;
9743412Snewton	bi->bi_op_abandon = 0;
9843412Snewton
9943412Snewton	bi->bi_extended = ldap_back_extended;
10043412Snewton
10143412Snewton	bi->bi_chk_referrals = 0;
10243412Snewton	bi->bi_entry_get_rw = ldap_back_entry_get;
10343412Snewton
10443412Snewton	bi->bi_connection_init = 0;
10543412Snewton	bi->bi_connection_destroy = ldap_back_conn_destroy;
10643412Snewton
10743412Snewton	bi->bi_extra = (void *)&ldap_extra;
10843412Snewton
10943412Snewton	rc =  ldap_back_init_cf( bi );
11043412Snewton	if ( rc ) {
11143412Snewton		return rc;
11243412Snewton	}
11343412Snewton
11443412Snewton	rc = chain_initialize();
11543412Snewton	if ( rc ) {
11643412Snewton		return rc;
11743412Snewton	}
11843412Snewton
11943412Snewton	rc = pbind_initialize();
12043412Snewton	if ( rc ) {
12143412Snewton		return rc;
12243412Snewton	}
12343412Snewton
12443412Snewton#ifdef SLAP_DISTPROC
12543412Snewton	rc = distproc_initialize();
12643412Snewton	if ( rc ) {
12743412Snewton		return rc;
12843412Snewton	}
12943412Snewton#endif
13043412Snewton	return rc;
13143412Snewton}
13243412Snewton
13343412Snewtonint
13443412Snewtonldap_back_db_init( Backend *be, ConfigReply *cr )
13543412Snewton{
13643412Snewton	ldapinfo_t	*li;
13743412Snewton	int		rc;
13843412Snewton	unsigned	i;
13943412Snewton
14043412Snewton	li = (ldapinfo_t *)ch_calloc( 1, sizeof( ldapinfo_t ) );
14143412Snewton	if ( li == NULL ) {
14243412Snewton 		return -1;
14343412Snewton 	}
14443412Snewton
14543412Snewton	li->li_rebind_f = ldap_back_default_rebind;
14643412Snewton	li->li_urllist_f = ldap_back_default_urllist;
14743412Snewton	li->li_urllist_p = li;
14843412Snewton	ldap_pvt_thread_mutex_init( &li->li_uri_mutex );
14943412Snewton
15043412Snewton	BER_BVZERO( &li->li_acl_authcID );
15143412Snewton	BER_BVZERO( &li->li_acl_authcDN );
15243412Snewton	BER_BVZERO( &li->li_acl_passwd );
15343412Snewton
15443412Snewton	li->li_acl_authmethod = LDAP_AUTH_NONE;
15543412Snewton	BER_BVZERO( &li->li_acl_sasl_mech );
15643412Snewton	li->li_acl.sb_tls = SB_TLS_DEFAULT;
15743412Snewton
15843412Snewton	li->li_idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
15943412Snewton
16043412Snewton	BER_BVZERO( &li->li_idassert_authcID );
16143412Snewton	BER_BVZERO( &li->li_idassert_authcDN );
16243412Snewton	BER_BVZERO( &li->li_idassert_passwd );
16343412Snewton
16443412Snewton	BER_BVZERO( &li->li_idassert_authzID );
16543412Snewton
16643412Snewton	li->li_idassert_authmethod = LDAP_AUTH_NONE;
16743412Snewton	BER_BVZERO( &li->li_idassert_sasl_mech );
16843412Snewton	li->li_idassert_tls = SB_TLS_DEFAULT;
16943412Snewton
17043412Snewton	/* by default, use proxyAuthz control on each operation */
17143412Snewton	li->li_idassert_flags = LDAP_BACK_AUTH_PRESCRIPTIVE;
17243412Snewton
17343412Snewton	li->li_idassert_authz = NULL;
17443412Snewton
17543412Snewton	/* initialize flags */
17643412Snewton	li->li_flags = LDAP_BACK_F_CHASE_REFERRALS;
17743412Snewton
17843412Snewton	/* initialize version */
17943412Snewton	li->li_version = LDAP_VERSION3;
18043412Snewton
18143412Snewton	ldap_pvt_thread_mutex_init( &li->li_conninfo.lai_mutex );
18243412Snewton
18343412Snewton	for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
18443412Snewton		li->li_conn_priv[ i ].lic_num = 0;
18543412Snewton		LDAP_TAILQ_INIT( &li->li_conn_priv[ i ].lic_priv );
18643412Snewton	}
18743412Snewton	li->li_conn_priv_max = LDAP_BACK_CONN_PRIV_DEFAULT;
18843412Snewton
18943412Snewton	ldap_pvt_thread_mutex_init( &li->li_counter_mutex );
19043412Snewton	for ( i = 0; i < SLAP_OP_LAST; i++ ) {
19143412Snewton		ldap_pvt_mp_init( li->li_ops_completed[ i ] );
19243412Snewton	}
19343412Snewton
19443412Snewton	li->li_conn_expire_task = NULL;
19543412Snewton
19643412Snewton	be->be_private = li;
19743412Snewton	SLAP_DBFLAGS( be ) |= SLAP_DBFLAG_NOLASTMOD;
19843412Snewton
19943412Snewton	be->be_cf_ocs = be->bd_info->bi_cf_ocs;
20043412Snewton
20143412Snewton	rc = ldap_back_monitor_db_init( be );
20243412Snewton	if ( rc != 0 ) {
20343412Snewton		/* ignore, by now */
20443412Snewton		rc = 0;
20543412Snewton	}
20643412Snewton
20743412Snewton	return rc;
20843412Snewton}
20943412Snewton
21043412Snewtonint
21143412Snewtonldap_back_db_open( BackendDB *be, ConfigReply *cr )
21243412Snewton{
21343412Snewton	ldapinfo_t	*li = (ldapinfo_t *)be->be_private;
21443412Snewton
21543412Snewton	slap_bindconf	sb = { BER_BVNULL };
21643412Snewton	int		rc = 0;
21743412Snewton
21843412Snewton	Debug( LDAP_DEBUG_TRACE,
21943412Snewton		"ldap_back_db_open: URI=%s\n",
22043412Snewton		li->li_uri != NULL ? li->li_uri : "" );
22143412Snewton
22243412Snewton	/* by default, use proxyAuthz control on each operation */
22343412Snewton	switch ( li->li_idassert_mode ) {
22443412Snewton	case LDAP_BACK_IDASSERT_LEGACY:
22543412Snewton	case LDAP_BACK_IDASSERT_SELF:
22643412Snewton		/* however, since admin connections are pooled and shared,
22743412Snewton		 * only static authzIDs can be native */
22843412Snewton		li->li_idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
22943412Snewton		break;
23043412Snewton
23143412Snewton	default:
23243412Snewton		break;
23343412Snewton	}
23443412Snewton
23543412Snewton	ber_str2bv( li->li_uri, 0, 0, &sb.sb_uri );
23643412Snewton	sb.sb_version = li->li_version;
23743412Snewton	sb.sb_method = LDAP_AUTH_SIMPLE;
23843412Snewton	BER_BVSTR( &sb.sb_binddn, "" );
23943412Snewton
24043412Snewton	if ( LDAP_BACK_T_F_DISCOVER( li ) && !LDAP_BACK_T_F( li ) ) {
24143412Snewton		rc = slap_discover_feature( &sb,
24243412Snewton				slap_schema.si_ad_supportedFeatures->ad_cname.bv_val,
24343412Snewton				LDAP_FEATURE_ABSOLUTE_FILTERS );
24443412Snewton		if ( rc == LDAP_COMPARE_TRUE ) {
24543412Snewton			li->li_flags |= LDAP_BACK_F_T_F;
24643412Snewton		}
24743412Snewton	}
24843412Snewton
24943412Snewton	if ( LDAP_BACK_CANCEL_DISCOVER( li ) && !LDAP_BACK_CANCEL( li ) ) {
25043412Snewton		rc = slap_discover_feature( &sb,
25143412Snewton				slap_schema.si_ad_supportedExtension->ad_cname.bv_val,
25243412Snewton				LDAP_EXOP_CANCEL );
25343412Snewton		if ( rc == LDAP_COMPARE_TRUE ) {
25443412Snewton			li->li_flags |= LDAP_BACK_F_CANCEL_EXOP;
25543412Snewton		}
25643412Snewton	}
25743412Snewton
25843412Snewton	/* monitor setup */
25943412Snewton	rc = ldap_back_monitor_db_open( be );
26043412Snewton	if ( rc != 0 ) {
26143412Snewton		/* ignore by now */
26243412Snewton		rc = 0;
26343412Snewton	}
26443412Snewton
26543412Snewton	li->li_flags |= LDAP_BACK_F_ISOPEN;
26643412Snewton
26743412Snewton	return rc;
26843412Snewton}
26943412Snewton
27043412Snewtonvoid
27143412Snewtonldap_back_conn_free( void *v_lc )
27243412Snewton{
27343412Snewton	ldapconn_t	*lc = v_lc;
27443412Snewton
27543412Snewton	if ( lc->lc_ld != NULL ) {
27643412Snewton		ldap_unbind_ext( lc->lc_ld, NULL, NULL );
27743412Snewton	}
27843412Snewton	if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
27943412Snewton		ch_free( lc->lc_bound_ndn.bv_val );
28043412Snewton	}
28143412Snewton	if ( !BER_BVISNULL( &lc->lc_cred ) ) {
28243412Snewton		memset( lc->lc_cred.bv_val, 0, lc->lc_cred.bv_len );
28343412Snewton		ch_free( lc->lc_cred.bv_val );
28443412Snewton	}
28543412Snewton	if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
28643412Snewton		ch_free( lc->lc_local_ndn.bv_val );
28743412Snewton	}
28843412Snewton	lc->lc_q.tqe_prev = NULL;
28943412Snewton	lc->lc_q.tqe_next = NULL;
29043412Snewton	ch_free( lc );
29143412Snewton}
29243412Snewton
29343412Snewtonint
29443412Snewtonldap_back_db_close( Backend *be, ConfigReply *cr )
29543412Snewton{
29643412Snewton	int		rc = 0;
29743412Snewton
29843412Snewton	if ( be->be_private ) {
29943412Snewton		rc = ldap_back_monitor_db_close( be );
30043412Snewton	}
30143412Snewton
30243412Snewton	return rc;
30343412Snewton}
30443412Snewton
30543412Snewtonint
30643412Snewtonldap_back_db_destroy( Backend *be, ConfigReply *cr )
30743412Snewton{
30843412Snewton	if ( be->be_private ) {
30943412Snewton		ldapinfo_t	*li = ( ldapinfo_t * )be->be_private;
31043412Snewton		unsigned	i;
31143412Snewton
31243412Snewton		(void)ldap_back_monitor_db_destroy( be );
31343412Snewton
31443412Snewton		/* Stop and remove the task that prunes expired connections */
31543412Snewton		if ( li->li_conn_expire_task != NULL ) {
31643412Snewton			ldap_pvt_thread_mutex_lock( &slapd_rq.rq_mutex );
31743412Snewton			if ( ldap_pvt_runqueue_isrunning( &slapd_rq, li->li_conn_expire_task ) ) {
31843412Snewton					ldap_pvt_runqueue_stoptask( &slapd_rq, li->li_conn_expire_task );
31943412Snewton			}
32043412Snewton			ldap_pvt_runqueue_remove( &slapd_rq, li->li_conn_expire_task );
32143412Snewton			ldap_pvt_thread_mutex_unlock( &slapd_rq.rq_mutex );
32243412Snewton		}
32343412Snewton
32443412Snewton		ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
32543412Snewton
32643412Snewton		if ( li->li_uri != NULL ) {
32743412Snewton			ch_free( li->li_uri );
32843412Snewton			li->li_uri = NULL;
32943412Snewton
33043412Snewton			assert( li->li_bvuri != NULL );
33143412Snewton			ber_bvarray_free( li->li_bvuri );
33243412Snewton			li->li_bvuri = NULL;
33343412Snewton		}
33443412Snewton
33543412Snewton		bindconf_free( &li->li_tls );
33643412Snewton		bindconf_free( &li->li_acl );
33743412Snewton		bindconf_free( &li->li_idassert.si_bc );
33843412Snewton
33943412Snewton		if ( li->li_idassert_authz != NULL ) {
34049267Snewton			ber_bvarray_free( li->li_idassert_authz );
34149267Snewton			li->li_idassert_authz = NULL;
34243412Snewton		}
34343412Snewton               	if ( li->li_conninfo.lai_tree ) {
34443412Snewton			ldap_tavl_free( li->li_conninfo.lai_tree, ldap_back_conn_free );
34543412Snewton		}
34643412Snewton		for ( i = LDAP_BACK_PCONN_FIRST; i < LDAP_BACK_PCONN_LAST; i++ ) {
34743412Snewton			while ( !LDAP_TAILQ_EMPTY( &li->li_conn_priv[ i ].lic_priv ) ) {
34843412Snewton				ldapconn_t	*lc = LDAP_TAILQ_FIRST( &li->li_conn_priv[ i ].lic_priv );
34943412Snewton
35043412Snewton				LDAP_TAILQ_REMOVE( &li->li_conn_priv[ i ].lic_priv, lc, lc_q );
35143412Snewton				ldap_back_conn_free( lc );
35243412Snewton			}
35343412Snewton		}
35443412Snewton		if ( LDAP_BACK_QUARANTINE( li ) ) {
35543412Snewton			slap_retry_info_destroy( &li->li_quarantine );
35643412Snewton			ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
35743412Snewton		}
35843412Snewton
35943412Snewton		ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
36043412Snewton		ldap_pvt_thread_mutex_destroy( &li->li_conninfo.lai_mutex );
36143412Snewton		ldap_pvt_thread_mutex_destroy( &li->li_uri_mutex );
36243412Snewton
36343412Snewton		for ( i = 0; i < SLAP_OP_LAST; i++ ) {
36443412Snewton			ldap_pvt_mp_clear( li->li_ops_completed[ i ] );
36543412Snewton		}
36643412Snewton		ldap_pvt_thread_mutex_destroy( &li->li_counter_mutex );
36743412Snewton	}
36843412Snewton
36943412Snewton	ch_free( be->be_private );
37043412Snewton
37143412Snewton	return 0;
37243412Snewton}
37343412Snewton
37443412Snewton#if SLAPD_LDAP == SLAPD_MOD_DYNAMIC
37543412Snewton
37643412Snewton/* conditionally define the init_module() function */
37743412SnewtonSLAP_BACKEND_INIT_MODULE( ldap )
37843412Snewton
37943412Snewton#endif /* SLAPD_LDAP == SLAPD_MOD_DYNAMIC */
38043412Snewton