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