static int vc_exop( Operation *op, SlapReply *rs ) { int rc = LDAP_SUCCESS; ber_tag_t tag; ber_len_t len = -1; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; struct berval reqdata = BER_BVNULL; struct berval cookie = BER_BVNULL; struct berval bdn = BER_BVNULL; ber_tag_t authtag; struct berval cred = BER_BVNULL; struct berval ndn = BER_BVNULL; struct berval mechanism = BER_BVNULL; vc_conn_t *conn = NULL; vc_cb_t vc = { 0 }; slap_callback sc = { 0 }; SlapReply rs2 = { 0 }; if ( op->ore_reqdata == NULL || op->ore_reqdata->bv_len == 0 ) { rs->sr_text = "empty request data field in VerifyCredentials exop"; return LDAP_PROTOCOL_ERROR; } /* optimistic */ rs->sr_err = LDAP_SUCCESS; ber_dupbv_x( &reqdata, op->ore_reqdata, op->o_tmpmemctx ); /* ber_init2 uses reqdata directly, doesn't allocate new buffers */ ber_init2( ber, &reqdata, 0 ); tag = ber_scanf( ber, "{" /*}*/ ); if ( tag != LBER_SEQUENCE ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE ) { /* * cookie: the pointer to the connection * of this operation */ ber_scanf( ber, "m", &cookie ); if ( cookie.bv_len != sizeof(Connection *) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } /* DN, authtag */ tag = ber_scanf( ber, "mt", &bdn, &authtag ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } rc = dnNormalize( 0, NULL, NULL, &bdn, &ndn, op->o_tmpmemctx ); if ( rc != LDAP_SUCCESS ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } switch ( authtag ) { case LDAP_AUTH_SIMPLE: /* cookie only makes sense for SASL bind (so far) */ if ( !BER_BVISNULL( &cookie ) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_scanf( ber, "m", &cred ); if ( tag == LBER_ERROR ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } break; case LDAP_AUTH_SASL: tag = ber_scanf( ber, "{s" /*}*/ , &mechanism ); if ( tag == LBER_ERROR || BER_BVISNULL( &mechanism ) || BER_BVISEMPTY( &mechanism ) ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } tag = ber_peek_tag( ber, &len ); if ( tag == LBER_OCTETSTRING ) { ber_scanf( ber, "m", &cred ); } tag = ber_scanf( ber, /*{*/ "}" ); break; default: rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } if ( !BER_BVISNULL( &cookie ) ) { vc_conn_t tmp = { 0 }; AC_MEMCPY( (char *)&tmp.conn, (const char *)cookie.bv_val, cookie.bv_len ); ldap_pvt_thread_mutex_lock( &vc_mutex ); conn = (vc_conn_t *)avl_find( vc_tree, (caddr_t)&tmp, vc_conn_cmp ); if ( conn == NULL || ( conn != NULL && conn->refcnt != 0 ) ) { conn = NULL; ldap_pvt_thread_mutex_unlock( &vc_mutex ); rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } conn->refcnt++; ldap_pvt_thread_mutex_unlock( &vc_mutex ); } else { void *thrctx; conn = (vc_conn_t *)SLAP_CALLOC( 1, sizeof( vc_conn_t ) ); conn->refcnt = 1; thrctx = ldap_pvt_thread_pool_context(); connection_fake_init2( &conn->connbuf, &conn->opbuf, thrctx, 0 ); conn->op = &conn->opbuf.ob_op; snprintf( conn->op->o_log_prefix, sizeof( conn->op->o_log_prefix ), "%s VERIFYCREDENTIALS", op->o_log_prefix ); } conn->op->o_tag = LDAP_REQ_BIND; memset( &conn->op->oq_bind, 0, sizeof( conn->op->oq_bind ) ); conn->op->o_req_dn = ndn; conn->op->o_req_ndn = ndn; conn->op->o_protocol = LDAP_VERSION3; conn->op->orb_method = authtag; conn->op->o_callback = ≻ /* TODO: controls */ tag = ber_peek_tag( ber, &len ); if ( tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ) { conn->op->o_ber = ber; rc = get_ctrls2( conn->op, &rs2, 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS ); if ( rc != LDAP_SUCCESS ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } } tag = ber_skip_tag( ber, &len ); if ( len || tag != LBER_DEFAULT ) { rs->sr_err = LDAP_PROTOCOL_ERROR; goto done; } switch ( authtag ) { case LDAP_AUTH_SIMPLE: break; case LDAP_AUTH_SASL: conn->op->orb_mech = mechanism; break; } conn->op->orb_cred = cred; sc.sc_response = vc_cb; sc.sc_private = &vc; conn->op->o_bd = frontendDB; rs->sr_err = frontendDB->be_bind( conn->op, &rs2 ); if ( conn->op->o_conn->c_sasl_bind_in_progress ) { rc = vc_create_response( conn, rs2.sr_err, rs2.sr_text, !BER_BVISEMPTY( &vc.sasldata ) ? &vc.sasldata : NULL, NULL, vc.ctrls, &rs->sr_rspdata ); } else { rc = vc_create_response( NULL, rs2.sr_err, rs2.sr_text, NULL, &conn->op->o_conn->c_dn, vc.ctrls, &rs->sr_rspdata ); } if ( rc != 0 ) { rs->sr_err = LDAP_OTHER; goto done; } if ( !BER_BVISNULL( &conn->op->o_conn->c_dn ) && conn->op->o_conn->c_dn.bv_val != conn->op->o_conn->c_ndn.bv_val ) ber_memfree( conn->op->o_conn->c_dn.bv_val ); if ( !BER_BVISNULL( &conn->op->o_conn->c_ndn ) ) ber_memfree( conn->op->o_conn->c_ndn.bv_val ); done:; if ( conn ) { if ( conn->op->o_conn->c_sasl_bind_in_progress ) { if ( conn->conn == NULL ) { conn->conn = conn; conn->refcnt--; ldap_pvt_thread_mutex_lock( &vc_mutex ); rc = avl_insert( &vc_tree, (caddr_t)conn, vc_conn_cmp, vc_conn_dup ); ldap_pvt_thread_mutex_unlock( &vc_mutex ); assert( rc == 0 ); } else { ldap_pvt_thread_mutex_lock( &vc_mutex ); conn->refcnt--; ldap_pvt_thread_mutex_unlock( &vc_mutex ); } } else { if ( conn->conn != NULL ) { vc_conn_t *tmp; ldap_pvt_thread_mutex_lock( &vc_mutex ); tmp = avl_delete( &vc_tree, (caddr_t)conn, vc_conn_cmp ); ldap_pvt_thread_mutex_unlock( &vc_mutex ); } SLAP_FREE( conn ); } } if ( vc.ctrls ) { ldap_controls_free( vc.ctrls ); vc.ctrls = NULL; } if ( !BER_BVISNULL( &ndn ) ) { op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); BER_BVZERO( &ndn ); } op->o_tmpfree( reqdata.bv_val, op->o_tmpmemctx ); BER_BVZERO( &reqdata ); return rs->sr_err; }
static int vernum_repair( BackendDB *be ) { slap_overinst *on = (slap_overinst *)be->bd_info; vernum_t *vn = (vernum_t *)on->on_bi.bi_private; void *ctx = ldap_pvt_thread_pool_context(); Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; BackendDB db; slap_callback sc = { 0 }; vernum_repair_cb_t rcb = { 0 }; SlapReply rs = { REP_RESULT }; vernum_mod_t *rmod; int nrepaired = 0; connection_fake_init2( &conn, &opbuf, ctx, 0 ); op = &opbuf.ob_op; op->o_tag = LDAP_REQ_SEARCH; memset( &op->oq_search, 0, sizeof( op->oq_search ) ); assert( !BER_BVISNULL( &be->be_nsuffix[ 0 ] ) ); op->o_bd = select_backend( &be->be_nsuffix[ 0 ], 0 ); assert( op->o_bd != NULL ); assert( op->o_bd->be_nsuffix != NULL ); op->o_req_dn = op->o_bd->be_suffix[ 0 ]; op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ]; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->ors_scope = LDAP_SCOPE_SUBTREE; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_no_attrs; op->ors_filterstr.bv_len = STRLENOF( "(&(=*)(!(=*)))" ) + vn->vn_attr->ad_cname.bv_len + vn->vn_vernum->ad_cname.bv_len; op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1, "(&(%s=*)(!(%s=*)))", vn->vn_attr->ad_cname.bv_val, vn->vn_vernum->ad_cname.bv_val ); op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val ); if ( op->ors_filter == NULL ) { rs.sr_err = LDAP_OTHER; goto done_search; } op->o_callback = ≻ sc.sc_response = vernum_repair_cb; sc.sc_private = &rcb; rcb.bd = &db; db = *be; db.bd_info = (BackendInfo *)on; (void)op->o_bd->bd_info->bi_op_search( op, &rs ); op->o_tag = LDAP_REQ_MODIFY; sc.sc_response = slap_null_cb; sc.sc_private = NULL; memset( &op->oq_modify, 0, sizeof( req_modify_s ) ); for ( rmod = rcb.mods; rmod != NULL; ) { vernum_mod_t *rnext; Modifications mod; struct berval vals[2] = { BER_BVNULL }; SlapReply rs2 = { REP_RESULT }; mod.sml_flags = SLAP_MOD_INTERNAL; mod.sml_op = LDAP_MOD_REPLACE; mod.sml_desc = vn->vn_vernum; mod.sml_type = vn->vn_vernum->ad_cname; mod.sml_values = vals; mod.sml_values[0] = val_init; mod.sml_nvalues = NULL; mod.sml_numvals = 1; mod.sml_next = NULL; op->o_req_dn = rmod->ndn; op->o_req_ndn = rmod->ndn; op->orm_modlist = &mod; op->o_bd->be_modify( op, &rs2 ); slap_mods_free( op->orm_modlist->sml_next, 1 ); if ( rs2.sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s: vernum_repair: entry DN=\"%s\" repaired\n", op->o_log_prefix, rmod->ndn.bv_val, 0 ); nrepaired++; } else { Debug( LDAP_DEBUG_ANY, "%s: vernum_repair: entry DN=\"%s\" repair failed (%d)\n", op->o_log_prefix, rmod->ndn.bv_val, rs2.sr_err ); } rnext = rmod->next; op->o_tmpfree( rmod, op->o_tmpmemctx ); rmod = rnext; } done_search:; op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter_free_x( op, op->ors_filter, 1 ); Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "vernum: repaired=%d\n", nrepaired ); return 0; }
static int autoca_db_open( BackendDB *be, ConfigReply *cr ) { slap_overinst *on = (slap_overinst *)be->bd_info; autoca_info *ai = on->on_bi.bi_private; Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; void *thrctx; Entry *e; Attribute *a; int rc; if (slapMode & SLAP_TOOL_MODE) return 0; if ( ! *aca_attr2[0].ad ) { int i, code; const char *text; for ( i=0; aca_attr2[i].at; i++ ) { code = slap_str2ad( aca_attr2[i].at, aca_attr2[i].ad, &text ); if ( code ) return code; } /* Schema may not be loaded, ignore if missing */ slap_str2ad( "ipHostNumber", &ad_ipaddr, &text ); for ( i=0; aca_ocs[i].ot; i++ ) { code = register_oc( aca_ocs[i].ot, aca_ocs[i].oc, 0 ); if ( code ) return code; } } thrctx = ldap_pvt_thread_pool_context(); connection_fake_init2( &conn, &opbuf, thrctx, 0 ); op = &opbuf.ob_op; op->o_bd = be; op->o_dn = be->be_rootdn; op->o_ndn = be->be_rootndn; rc = overlay_entry_get_ov( op, be->be_nsuffix, NULL, NULL, 0, &e, on ); if ( e ) { int gotoc = 0, gotat = 0; if ( is_entry_objectclass( e, oc_caObj, 0 )) { gotoc = 1; a = attr_find( e->e_attrs, ad_caPkey ); if ( a ) { const unsigned char *pp; pp = (unsigned char *)a->a_vals[0].bv_val; ai->ai_pkey = d2i_AutoPrivateKey( NULL, &pp, a->a_vals[0].bv_len ); if ( ai->ai_pkey ) { a = attr_find( e->e_attrs, ad_caCert ); if ( a ) { pp = (unsigned char *)a->a_vals[0].bv_val; ai->ai_cert = d2i_X509( NULL, &pp, a->a_vals[0].bv_len ); /* If TLS wasn't configured yet, set this as our CA */ if ( !slap_tls_ctx ) autoca_setca( a->a_vals ); } } gotat = 1; } } overlay_entry_release_ov( op, e, 0, on ); /* generate attrs, store... */ if ( !gotat ) { genargs args; saveargs arg2; args.issuer_cert = NULL; args.issuer_pkey = NULL; args.subjectDN = &be->be_suffix[0]; args.cert_exts = CAexts; args.more_exts = NULL; args.keybits = ai->ai_cakeybits; args.days = ai->ai_cadays; rc = autoca_gencert( op, &args ); if ( rc ) return -1; ai->ai_cert = args.newcert; ai->ai_pkey = args.newpkey; arg2.dn = be->be_suffix; arg2.ndn = be->be_nsuffix; arg2.isca = 1; if ( !gotoc ) arg2.oc = oc_caObj; else arg2.oc = NULL; arg2.on = on; arg2.dercert = &args.dercert; arg2.derpkey = &args.derpkey; autoca_savecert( op, &arg2 ); /* If TLS wasn't configured yet, set this as our CA */ if ( !slap_tls_ctx ) autoca_setca( &args.dercert ); op->o_tmpfree( args.dercert.bv_val, op->o_tmpmemctx ); op->o_tmpfree( args.derpkey.bv_val, op->o_tmpmemctx ); } } return 0; }
static int pguid_repair( BackendDB *be ) { slap_overinst *on = (slap_overinst *)be->bd_info; void *ctx = ldap_pvt_thread_pool_context(); Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; slap_callback sc = { 0 }; pguid_repair_cb_t pcb = { 0 }; SlapReply rs = { REP_RESULT }; pguid_mod_t *pmod; int nrepaired = 0; connection_fake_init2( &conn, &opbuf, ctx, 0 ); op = &opbuf.ob_op; op->o_tag = LDAP_REQ_SEARCH; memset( &op->oq_search, 0, sizeof( op->oq_search ) ); op->o_bd = select_backend( &be->be_nsuffix[ 0 ], 0 ); op->o_req_dn = op->o_bd->be_suffix[ 0 ]; op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ]; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->ors_scope = LDAP_SCOPE_SUBORDINATE; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_no_attrs; op->ors_filterstr.bv_len = STRLENOF( "(!(=*))" ) + ad_parentUUID->ad_cname.bv_len; op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1, "(!(%s=*))", ad_parentUUID->ad_cname.bv_val ); op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val ); if ( op->ors_filter == NULL ) { rs.sr_err = LDAP_OTHER; goto done_search; } op->o_callback = ≻ sc.sc_response = pguid_repair_cb; sc.sc_private = &pcb; pcb.on = on; (void)op->o_bd->bd_info->bi_op_search( op, &rs ); op->o_tag = LDAP_REQ_MODIFY; sc.sc_response = slap_null_cb; sc.sc_private = NULL; memset( &op->oq_modify, 0, sizeof( req_modify_s ) ); for ( pmod = pcb.mods; pmod != NULL; ) { pguid_mod_t *pnext; Modifications *mod; SlapReply rs2 = { REP_RESULT }; mod = (Modifications *) ch_malloc( sizeof( Modifications ) ); mod->sml_flags = SLAP_MOD_INTERNAL; mod->sml_op = LDAP_MOD_REPLACE; mod->sml_desc = ad_parentUUID; mod->sml_type = ad_parentUUID->ad_cname; mod->sml_values = ch_malloc( sizeof( struct berval ) * 2 ); mod->sml_nvalues = NULL; mod->sml_numvals = 1; mod->sml_next = NULL; ber_dupbv( &mod->sml_values[0], &pmod->pguid ); BER_BVZERO( &mod->sml_values[1] ); op->o_req_dn = pmod->ndn; op->o_req_ndn = pmod->ndn; op->orm_modlist = mod; op->o_bd->be_modify( op, &rs2 ); slap_mods_free( op->orm_modlist, 1 ); if ( rs2.sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "%s: pguid_repair: entry DN=\"%s\" repaired\n", op->o_log_prefix, pmod->ndn.bv_val, 0 ); nrepaired++; } else { Debug( LDAP_DEBUG_ANY, "%s: pguid_repair: entry DN=\"%s\" repair failed (%d)\n", op->o_log_prefix, pmod->ndn.bv_val, rs2.sr_err ); } pnext = pmod->next; op->o_tmpfree( pmod, op->o_tmpmemctx ); pmod = pnext; } done_search:; op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter_free_x( op, op->ors_filter, 1 ); Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "pguid: repaired=%d\n", nrepaired ); return rs.sr_err; }
int backsql_db_open( BackendDB *bd, ConfigReply *cr ) { backsql_info *bi = (backsql_info*)bd->be_private; struct berbuf bb = BB_NULL; Connection conn = { 0 }; OperationBuffer opbuf; Operation* op; SQLHDBC dbh = SQL_NULL_HDBC; void *thrctx = ldap_pvt_thread_pool_context(); Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): " "testing RDBMS connection\n", 0, 0, 0 ); if ( bi->sql_dbname == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "datasource name not specified " "(use \"dbname\" directive in slapd.conf)\n", 0, 0, 0 ); return 1; } if ( bi->sql_concat_func == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "concat func not specified (use \"concat_pattern\" " "directive in slapd.conf)\n", 0, 0, 0 ); if ( backsql_split_pattern( backsql_def_concat_func, &bi->sql_concat_func, 2 ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "unable to parse pattern \"%s\"", backsql_def_concat_func, 0, 0 ); return 1; } } /* * see back-sql.h for default values */ if ( BER_BVISNULL( &bi->sql_aliasing ) ) { ber_str2bv( BACKSQL_ALIASING, STRLENOF( BACKSQL_ALIASING ), 1, &bi->sql_aliasing ); } if ( BER_BVISNULL( &bi->sql_aliasing_quote ) ) { ber_str2bv( BACKSQL_ALIASING_QUOTE, STRLENOF( BACKSQL_ALIASING_QUOTE ), 1, &bi->sql_aliasing_quote ); } /* * Prepare cast string as required */ if ( bi->sql_upper_func.bv_val ) { char buf[1024]; if ( BACKSQL_UPPER_NEEDS_CAST( bi ) ) { snprintf( buf, sizeof( buf ), "%s(cast (" /* ? as varchar(%d))) */ , bi->sql_upper_func.bv_val ); ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open ); snprintf( buf, sizeof( buf ), /* (cast(? */ " as varchar(%d)))", BACKSQL_MAX_DN_LEN ); ber_str2bv( buf, 0, 1, &bi->sql_upper_func_close ); } else { snprintf( buf, sizeof( buf ), "%s(" /* ?) */ , bi->sql_upper_func.bv_val ); ber_str2bv( buf, 0, 1, &bi->sql_upper_func_open ); ber_str2bv( /* (? */ ")", 0, 1, &bi->sql_upper_func_close ); } } /* normalize filter values only if necessary */ bi->sql_caseIgnoreMatch = mr_find( "caseIgnoreMatch" ); assert( bi->sql_caseIgnoreMatch != NULL ); bi->sql_telephoneNumberMatch = mr_find( "telephoneNumberMatch" ); assert( bi->sql_telephoneNumberMatch != NULL ); if ( bi->sql_dbuser == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "user name not specified " "(use \"dbuser\" directive in slapd.conf)\n", 0, 0, 0 ); return 1; } if ( BER_BVISNULL( &bi->sql_subtree_cond ) ) { /* * Prepare concat function for subtree search condition */ struct berval concat; struct berval values[] = { BER_BVC( "'%'" ), BER_BVC( "?" ), BER_BVNULL }; struct berbuf bb = BB_NULL; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "subtree search SQL condition not specified " "(use \"subtree_cond\" directive in slapd.conf); " "preparing default\n", 0, 0, 0); if ( backsql_prepare_pattern( bi->sql_concat_func, values, &concat ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "unable to prepare CONCAT pattern for subtree search", 0, 0, 0 ); return 1; } if ( bi->sql_upper_func.bv_val ) { /* * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?)) */ backsql_strfcat_x( &bb, NULL, "blbbb", &bi->sql_upper_func, (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ), "(ldap_entries.dn) LIKE ", &bi->sql_upper_func_open, &concat, &bi->sql_upper_func_close ); } else { /* * ldap_entries.dn LIKE CONCAT('%',?) */ backsql_strfcat_x( &bb, NULL, "lb", (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ), "ldap_entries.dn LIKE ", &concat ); } ch_free( concat.bv_val ); bi->sql_subtree_cond = bb.bb_val; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" as default \"subtree_cond\"\n", bi->sql_subtree_cond.bv_val, 0, 0 ); } if ( bi->sql_children_cond.bv_val == NULL ) { /* * Prepare concat function for children search condition */ struct berval concat; struct berval values[] = { BER_BVC( "'%,'" ), BER_BVC( "?" ), BER_BVNULL }; struct berbuf bb = BB_NULL; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "children search SQL condition not specified " "(use \"children_cond\" directive in slapd.conf); " "preparing default\n", 0, 0, 0); if ( backsql_prepare_pattern( bi->sql_concat_func, values, &concat ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "unable to prepare CONCAT pattern for children search", 0, 0, 0 ); return 1; } if ( bi->sql_upper_func.bv_val ) { /* * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?)) */ backsql_strfcat_x( &bb, NULL, "blbbb", &bi->sql_upper_func, (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE " ), "(ldap_entries.dn) LIKE ", &bi->sql_upper_func_open, &concat, &bi->sql_upper_func_close ); } else { /* * ldap_entries.dn LIKE CONCAT('%,',?) */ backsql_strfcat_x( &bb, NULL, "lb", (ber_len_t)STRLENOF( "ldap_entries.dn LIKE " ), "ldap_entries.dn LIKE ", &concat ); } ch_free( concat.bv_val ); bi->sql_children_cond = bb.bb_val; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" as default \"children_cond\"\n", bi->sql_children_cond.bv_val, 0, 0 ); } if ( bi->sql_dn_match_cond.bv_val == NULL ) { /* * Prepare concat function for dn match search condition */ struct berbuf bb = BB_NULL; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "DN match search SQL condition not specified " "(use \"dn_match_cond\" directive in slapd.conf); " "preparing default\n", 0, 0, 0); if ( bi->sql_upper_func.bv_val ) { /* * UPPER(ldap_entries.dn)=? */ backsql_strfcat_x( &bb, NULL, "blbcb", &bi->sql_upper_func, (ber_len_t)STRLENOF( "(ldap_entries.dn)=" ), "(ldap_entries.dn)=", &bi->sql_upper_func_open, '?', &bi->sql_upper_func_close ); } else { /* * ldap_entries.dn=? */ backsql_strfcat_x( &bb, NULL, "l", (ber_len_t)STRLENOF( "ldap_entries.dn=?" ), "ldap_entries.dn=?" ); } bi->sql_dn_match_cond = bb.bb_val; Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" as default \"dn_match_cond\"\n", bi->sql_dn_match_cond.bv_val, 0, 0 ); } if ( bi->sql_oc_query == NULL ) { if ( BACKSQL_CREATE_NEEDS_SELECT( bi ) ) { bi->sql_oc_query = ch_strdup( backsql_def_needs_select_oc_query ); } else { bi->sql_oc_query = ch_strdup( backsql_def_oc_query ); } Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "objectclass mapping SQL statement not specified " "(use \"oc_query\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", bi->sql_oc_query, 0, 0 ); } if ( bi->sql_at_query == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "attribute mapping SQL statement not specified " "(use \"at_query\" directive in slapd.conf)\n", 0, 0, 0 ); Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", backsql_def_at_query, 0, 0 ); bi->sql_at_query = ch_strdup( backsql_def_at_query ); } if ( bi->sql_insentry_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "entry insertion SQL statement not specified " "(use \"insentry_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", backsql_def_insentry_stmt, 0, 0 ); bi->sql_insentry_stmt = ch_strdup( backsql_def_insentry_stmt ); } if ( bi->sql_delentry_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "entry deletion SQL statement not specified " "(use \"delentry_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", backsql_def_delentry_stmt, 0, 0 ); bi->sql_delentry_stmt = ch_strdup( backsql_def_delentry_stmt ); } if ( bi->sql_renentry_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "entry deletion SQL statement not specified " "(use \"renentry_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", backsql_def_renentry_stmt, 0, 0 ); bi->sql_renentry_stmt = ch_strdup( backsql_def_renentry_stmt ); } if ( bi->sql_delobjclasses_stmt == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "objclasses deletion SQL statement not specified " "(use \"delobjclasses_stmt\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting \"%s\" by default\n", backsql_def_delobjclasses_stmt, 0, 0 ); bi->sql_delobjclasses_stmt = ch_strdup( backsql_def_delobjclasses_stmt ); } /* This should just be to force schema loading */ connection_fake_init2( &conn, &opbuf, thrctx, 0 ); op = &opbuf.ob_op; op->o_bd = bd; if ( backsql_get_db_conn( op, &dbh ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "connection failed, exiting\n", 0, 0, 0 ); return 1; } if ( backsql_load_schema_map( bi, dbh ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "schema mapping failed, exiting\n", 0, 0, 0 ); return 1; } if ( backsql_free_db_conn( op, dbh ) != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "connection free failed\n", 0, 0, 0 ); } if ( !BACKSQL_SCHEMA_LOADED( bi ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "test failed, schema map not loaded - exiting\n", 0, 0, 0 ); return 1; } /* * Prepare ID selection query */ if ( bi->sql_id_query == NULL ) { /* no custom id_query provided */ if ( bi->sql_upper_func.bv_val == NULL ) { backsql_strcat_x( &bb, NULL, backsql_id_query, "dn=?", NULL ); } else { if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) { backsql_strcat_x( &bb, NULL, backsql_id_query, "dn_ru=?", NULL ); } else { if ( BACKSQL_USE_REVERSE_DN( bi ) ) { backsql_strfcat_x( &bb, NULL, "sbl", backsql_id_query, &bi->sql_upper_func, (ber_len_t)STRLENOF( "(dn)=?" ), "(dn)=?" ); } else { backsql_strfcat_x( &bb, NULL, "sblbcb", backsql_id_query, &bi->sql_upper_func, (ber_len_t)STRLENOF( "(dn)=" ), "(dn)=", &bi->sql_upper_func_open, '?', &bi->sql_upper_func_close ); } } } bi->sql_id_query = bb.bb_val.bv_val; } /* * Prepare children count query */ BER_BVZERO( &bb.bb_val ); bb.bb_len = 0; backsql_strfcat_x( &bb, NULL, "sbsb", "SELECT COUNT(distinct subordinates.id) " "FROM ldap_entries,ldap_entries ", &bi->sql_aliasing, "subordinates " "WHERE subordinates.parent=ldap_entries.id AND ", &bi->sql_dn_match_cond ); bi->sql_has_children_query = bb.bb_val.bv_val; /* * Prepare DN and objectClass aliasing bit of query */ BER_BVZERO( &bb.bb_val ); bb.bb_len = 0; backsql_strfcat_x( &bb, NULL, "sbbsbsbbsb", " ", &bi->sql_aliasing, &bi->sql_aliasing_quote, "objectClass", &bi->sql_aliasing_quote, ",ldap_entries.dn ", &bi->sql_aliasing, &bi->sql_aliasing_quote, "dn", &bi->sql_aliasing_quote ); bi->sql_dn_oc_aliasing = bb.bb_val; /* should never happen! */ assert( bd->be_nsuffix != NULL ); if ( BER_BVISNULL( &bd->be_nsuffix[ 1 ] ) ) { /* enable if only one suffix is defined */ bi->sql_flags |= BSQLF_USE_SUBTREE_SHORTCUT; } bi->sql_flags |= BSQLF_CHECK_SCHEMA; Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): " "test succeeded, schema map loaded\n", 0, 0, 0 ); return 0; }
/* count dynamic objects existing in the database at startup */ static int dds_count( void *ctx, BackendDB *be ) { slap_overinst *on = (slap_overinst *)be->bd_info; dds_info_t *di = (dds_info_t *)on->on_bi.bi_private; Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; slap_callback sc = { 0 }; SlapReply rs = { REP_RESULT }; int rc; char *extra = ""; connection_fake_init2( &conn, &opbuf, ctx, 0 ); op = &opbuf.ob_op; op->o_tag = LDAP_REQ_SEARCH; memset( &op->oq_search, 0, sizeof( op->oq_search ) ); op->o_bd = be; op->o_req_dn = op->o_bd->be_suffix[ 0 ]; op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ]; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->ors_scope = LDAP_SCOPE_SUBTREE; op->ors_tlimit = SLAP_NO_LIMIT; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_no_attrs; op->ors_filterstr.bv_len = STRLENOF( "(objectClass=" ")" ) + slap_schema.si_oc_dynamicObject->soc_cname.bv_len; op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1, "(objectClass=%s)", slap_schema.si_oc_dynamicObject->soc_cname.bv_val ); op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val ); if ( op->ors_filter == NULL ) { rs.sr_err = LDAP_OTHER; goto done_search; } op->o_callback = ≻ sc.sc_response = dds_count_cb; sc.sc_private = &di->di_num_dynamicObjects; di->di_num_dynamicObjects = 0; op->o_bd->bd_info = (BackendInfo *)on->on_info; (void)op->o_bd->bd_info->bi_op_search( op, &rs ); op->o_bd->bd_info = (BackendInfo *)on; done_search:; op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter_free_x( op, op->ors_filter, 1 ); rc = rs.sr_err; switch ( rs.sr_err ) { case LDAP_SUCCESS: Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "DDS non-expired=%d\n", di->di_num_dynamicObjects ); break; case LDAP_NO_SUCH_OBJECT: /* (ITS#5267) database not created yet? */ rs.sr_err = LDAP_SUCCESS; extra = " (ignored)"; /* fallthru */ default: Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "DDS non-expired objects lookup failed err=%d%s\n", rc, extra ); break; } return rs.sr_err; }
static int dds_expire( void *ctx, dds_info_t *di ) { Connection conn = { 0 }; OperationBuffer opbuf; Operation *op; slap_callback sc = { 0 }; dds_cb_t dc = { 0 }; dds_expire_t *de = NULL, **dep; SlapReply rs = { REP_RESULT }; time_t expire; char tsbuf[ LDAP_LUTIL_GENTIME_BUFSIZE ]; struct berval ts; int ndeletes, ntotdeletes; int rc; char *extra = ""; connection_fake_init2( &conn, &opbuf, ctx, 0 ); op = &opbuf.ob_op; op->o_tag = LDAP_REQ_SEARCH; memset( &op->oq_search, 0, sizeof( op->oq_search ) ); op->o_bd = select_backend( &di->di_nsuffix[ 0 ], 0 ); op->o_req_dn = op->o_bd->be_suffix[ 0 ]; op->o_req_ndn = op->o_bd->be_nsuffix[ 0 ]; op->o_dn = op->o_bd->be_rootdn; op->o_ndn = op->o_bd->be_rootndn; op->ors_scope = LDAP_SCOPE_SUBTREE; op->ors_tlimit = DDS_INTERVAL( di )/2 + 1; op->ors_slimit = SLAP_NO_LIMIT; op->ors_attrs = slap_anlist_no_attrs; expire = slap_get_time() - di->di_tolerance; ts.bv_val = tsbuf; ts.bv_len = sizeof( tsbuf ); slap_timestamp( &expire, &ts ); op->ors_filterstr.bv_len = STRLENOF( "(&(objectClass=" ")(" "<=" "))" ) + slap_schema.si_oc_dynamicObject->soc_cname.bv_len + ad_entryExpireTimestamp->ad_cname.bv_len + ts.bv_len; op->ors_filterstr.bv_val = op->o_tmpalloc( op->ors_filterstr.bv_len + 1, op->o_tmpmemctx ); snprintf( op->ors_filterstr.bv_val, op->ors_filterstr.bv_len + 1, "(&(objectClass=%s)(%s<=%s))", slap_schema.si_oc_dynamicObject->soc_cname.bv_val, ad_entryExpireTimestamp->ad_cname.bv_val, ts.bv_val ); op->ors_filter = str2filter_x( op, op->ors_filterstr.bv_val ); if ( op->ors_filter == NULL ) { rs.sr_err = LDAP_OTHER; goto done_search; } op->o_callback = ≻ sc.sc_response = dds_expire_cb; sc.sc_private = &dc; (void)op->o_bd->bd_info->bi_op_search( op, &rs ); done_search:; op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx ); filter_free_x( op, op->ors_filter, 1 ); rc = rs.sr_err; switch ( rs.sr_err ) { case LDAP_SUCCESS: break; case LDAP_NO_SUCH_OBJECT: /* (ITS#5267) database not created yet? */ rs.sr_err = LDAP_SUCCESS; extra = " (ignored)"; /* fallthru */ default: Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_ERR, "DDS expired objects lookup failed err=%d%s\n", rc, extra ); goto done; } op->o_tag = LDAP_REQ_DELETE; op->o_callback = ≻ sc.sc_response = slap_null_cb; sc.sc_private = NULL; slap_biglock_acquire(op->o_bd); for ( ntotdeletes = 0, ndeletes = 1; dc.dc_ndnlist != NULL && ndeletes > 0; ) { ndeletes = 0; for ( dep = &dc.dc_ndnlist; *dep != NULL; ) { de = *dep; op->o_req_dn = de->de_ndn; op->o_req_ndn = de->de_ndn; (void)op->o_bd->bd_info->bi_op_delete( op, &rs ); switch ( rs.sr_err ) { case LDAP_SUCCESS: Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "DDS dn=\"%s\" expired.\n", de->de_ndn.bv_val ); ndeletes++; break; case LDAP_NOT_ALLOWED_ON_NONLEAF: Log1( LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE, "DDS dn=\"%s\" is non-leaf; " "deferring.\n", de->de_ndn.bv_val ); dep = &de->de_next; de = NULL; break; default: Log2( LDAP_DEBUG_ANY, LDAP_LEVEL_NOTICE, "DDS dn=\"%s\" err=%d; " "deferring.\n", de->de_ndn.bv_val, rs.sr_err ); break; } if ( de != NULL ) { *dep = de->de_next; op->o_tmpfree( de, op->o_tmpmemctx ); } } ntotdeletes += ndeletes; } slap_biglock_release(op->o_bd); rs.sr_err = LDAP_SUCCESS; Log1( LDAP_DEBUG_STATS, LDAP_LEVEL_INFO, "DDS expired=%d\n", ntotdeletes ); done:; return rs.sr_err; }