int backsql_bind( Operation *op, SlapReply *rs ) { SQLHDBC dbh = SQL_NULL_HDBC; Entry e = { 0 }; Attribute *a; backsql_srch_info bsi = { 0 }; AttributeName anlist[2]; int rc; Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 ); switch ( be_rootdn_bind( op, rs ) ) { case SLAP_CB_CONTINUE: break; default: /* in case of success, front end will send result; * otherwise, be_rootdn_bind() did */ Debug( LDAP_DEBUG_TRACE, "<==backsql_bind(%d)\n", rs->sr_err, 0, 0 ); return rs->sr_err; } rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_bind(): " "could not get connection handle - exiting\n", 0, 0, 0 ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; goto error_return; } anlist[0].an_name = slap_schema.si_ad_userPassword->ad_cname; anlist[0].an_desc = slap_schema.si_ad_userPassword; anlist[1].an_name.bv_val = NULL; bsi.bsi_e = &e; rc = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, anlist, BACKSQL_ISF_GET_ENTRY ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_bind(): " "could not retrieve bindDN ID - no such entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } a = attr_find( e.e_attrs, slap_schema.si_ad_userPassword ); if ( a == NULL ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } if ( slap_passwd_check( op, &e, a, &op->oq_bind.rb_cred, &rs->sr_text ) != 0 ) { rs->sr_err = LDAP_INVALID_CREDENTIALS; goto error_return; } error_return:; if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &e.e_nname ) ) { backsql_entry_clean( op, &e ); } if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); } Debug( LDAP_DEBUG_TRACE,"<==backsql_bind()\n", 0, 0, 0 ); return rs->sr_err; }
int backsql_delete( Operation *op, SlapReply *rs ) { SQLHDBC dbh = SQL_NULL_HDBC; SQLHSTMT sth = SQL_NULL_HSTMT; backsql_oc_map_rec *oc = NULL; backsql_srch_info bsi = { 0 }; backsql_entryID e_id = { 0 }; Entry d = { 0 }, p = { 0 }, *e = NULL; struct berval pdn = BER_BVNULL; int manageDSAit = get_manageDSAit( op ); Debug( LDAP_DEBUG_TRACE, "==>backsql_delete(): deleting entry \"%s\"\n", op->o_req_ndn.bv_val, 0, 0 ); rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "could not get connection handle - exiting\n", 0, 0, 0 ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; e = NULL; goto done; } /* * Get the entry */ bsi.bsi_e = &d; rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) ); switch ( rs->sr_err ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } e = &d; /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_delete(): " "could not retrieve deleteDN ID - no such entry\n", 0, 0, 0 ); if ( !BER_BVISNULL( &d.e_nname ) ) { /* FIXME: should always be true! */ e = &d; } else { e = NULL; } goto done; } if ( get_assert( op ) && ( test_filter( op, &d, get_assertion( op ) ) != LDAP_COMPARE_TRUE ) ) { rs->sr_err = LDAP_ASSERTION_FAILED; e = &d; goto done; } if ( !access_allowed( op, &d, slap_schema.si_ad_entry, NULL, ACL_WDEL, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "no write access to entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; e = &d; goto done; } rs->sr_err = backsql_has_children( op, dbh, &op->o_req_ndn ); switch ( rs->sr_err ) { case LDAP_COMPARE_FALSE: rs->sr_err = LDAP_SUCCESS; break; case LDAP_COMPARE_TRUE: #ifdef SLAP_CONTROL_X_TREE_DELETE if ( get_treeDelete( op ) ) { rs->sr_err = LDAP_SUCCESS; break; } #endif /* SLAP_CONTROL_X_TREE_DELETE */ Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "entry \"%s\" has children\n", op->o_req_dn.bv_val, 0, 0 ); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subordinate objects must be deleted first"; /* fallthru */ default: e = &d; goto done; } assert( bsi.bsi_base_id.eid_oc != NULL ); oc = bsi.bsi_base_id.eid_oc; if ( oc->bom_delete_proc == NULL ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "delete procedure is not defined " "for this objectclass - aborting\n", 0, 0, 0 ); rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "operation not permitted within namingContext"; e = NULL; goto done; } /* * Get the parent */ e_id = bsi.bsi_base_id; memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) ); if ( !be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_ndn, &pdn ); bsi.bsi_e = &p; rs->sr_err = backsql_init_search( &bsi, &pdn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_no_attrs, BACKSQL_ISF_GET_ENTRY ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_delete(): " "could not retrieve deleteDN ID " "- no such entry\n", 0, 0, 0 ); e = &p; goto done; } (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); /* check parent for "children" acl */ if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL, ACL_WDEL, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " "no write access to parent\n", 0, 0, 0 ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; e = &p; goto done; } } e = &d; #ifdef SLAP_CONTROL_X_TREE_DELETE if ( get_treeDelete( op ) ) { backsql_tree_delete( op, rs, dbh, &sth ); if ( rs->sr_err == LDAP_OTHER || rs->sr_err == LDAP_SUCCESS ) { e = NULL; } } else #endif /* SLAP_CONTROL_X_TREE_DELETE */ { backsql_delete_int( op, rs, dbh, &sth, &e_id, &e ); } /* * Commit only if all operations succeed */ if ( sth != SQL_NULL_HSTMT ) { SQLUSMALLINT CompletionType = SQL_ROLLBACK; if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { assert( e == NULL ); CompletionType = SQL_COMMIT; } SQLTransact( SQL_NULL_HENV, dbh, CompletionType ); } done:; if ( e != NULL ) { if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } } if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) { rs->sr_err = LDAP_X_NO_OPERATION; } send_ldap_result( op, rs ); Debug( LDAP_DEBUG_TRACE, "<==backsql_delete()\n", 0, 0, 0 ); if ( !BER_BVISNULL( &e_id.eid_ndn ) ) { (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &d.e_nname ) ) { backsql_entry_clean( op, &d ); } if ( !BER_BVISNULL( &p.e_nname ) ) { backsql_entry_clean( op, &p ); } if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } return rs->sr_err; }
int backsql_modify( Operation *op, SlapReply *rs ) { backsql_info *bi = (backsql_info*)op->o_bd->be_private; SQLHDBC dbh = SQL_NULL_HDBC; backsql_oc_map_rec *oc = NULL; backsql_srch_info bsi = { 0 }; Entry m = { 0 }, *e = NULL; int manageDSAit = get_manageDSAit( op ); SQLUSMALLINT CompletionType = SQL_ROLLBACK; /* * FIXME: in case part of the operation cannot be performed * (missing mapping, SQL write fails or so) the entire operation * should be rolled-back */ Debug( LDAP_DEBUG_TRACE, "==>backsql_modify(): modifying entry \"%s\"\n", op->o_req_ndn.bv_val, 0, 0 ); rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modify(): " "could not get connection handle - exiting\n", 0, 0, 0 ); /* * FIXME: we don't want to send back * excessively detailed messages */ rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; goto done; } bsi.bsi_e = &m; rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) ); switch ( rs->sr_err ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } e = &m; /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_modify(): " "could not retrieve modifyDN ID - no such entry\n", 0, 0, 0 ); if ( !BER_BVISNULL( &m.e_nname ) ) { /* FIXME: should always be true! */ e = &m; } else { e = NULL; } goto done; } #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, " backsql_modify(): " "modifying entry \"%s\" (id=%s)\n", bsi.bsi_base_id.eid_dn.bv_val, bsi.bsi_base_id.eid_id.bv_val, 0 ); #else /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, " backsql_modify(): " "modifying entry \"%s\" (id=%ld)\n", bsi.bsi_base_id.eid_dn.bv_val, bsi.bsi_base_id.eid_id, 0 ); #endif /* ! BACKSQL_ARBITRARY_KEY */ if ( get_assert( op ) && ( test_filter( op, &m, get_assertion( op ) ) != LDAP_COMPARE_TRUE )) { rs->sr_err = LDAP_ASSERTION_FAILED; e = &m; goto done; } slap_mods_opattrs( op, &op->orm_modlist, 1 ); assert( bsi.bsi_base_id.eid_oc != NULL ); oc = bsi.bsi_base_id.eid_oc; if ( !acl_check_modlist( op, &m, op->orm_modlist ) ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; e = &m; goto done; } rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &bsi.bsi_base_id, op->orm_modlist ); if ( rs->sr_err != LDAP_SUCCESS ) { e = &m; goto do_transact; } if ( BACKSQL_CHECK_SCHEMA( bi ) ) { char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' }; backsql_entry_clean( op, &m ); bsi.bsi_e = &m; rs->sr_err = backsql_id2entry( &bsi, &bsi.bsi_base_id ); if ( rs->sr_err != LDAP_SUCCESS ) { e = &m; goto do_transact; } rs->sr_err = entry_schema_check( op, &m, NULL, 0, 0, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modify(\"%s\"): " "entry failed schema check -- aborting\n", m.e_name.bv_val, 0, 0 ); e = NULL; goto do_transact; } } do_transact:; /* * Commit only if all operations succeed */ if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { assert( e == NULL ); CompletionType = SQL_COMMIT; } SQLTransact( SQL_NULL_HENV, dbh, CompletionType ); done:; if ( e != NULL ) { if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } } if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) { rs->sr_err = LDAP_X_NO_OPERATION; } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &m.e_nname ) ) { backsql_entry_clean( op, &m ); } if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } Debug( LDAP_DEBUG_TRACE, "<==backsql_modify()\n", 0, 0, 0 ); return rs->sr_err; }
int backsql_modrdn( Operation *op, SlapReply *rs ) { backsql_info *bi = (backsql_info*)op->o_bd->be_private; SQLHDBC dbh = SQL_NULL_HDBC; SQLHSTMT sth = SQL_NULL_HSTMT; RETCODE rc; backsql_entryID e_id = BACKSQL_ENTRYID_INIT, n_id = BACKSQL_ENTRYID_INIT; backsql_srch_info bsi = { 0 }; backsql_oc_map_rec *oc = NULL; struct berval pdn = BER_BVNULL, pndn = BER_BVNULL, *new_pdn = NULL, *new_npdn = NULL, new_dn = BER_BVNULL, new_ndn = BER_BVNULL, realnew_dn = BER_BVNULL; Entry r = { 0 }, p = { 0 }, n = { 0 }, *e = NULL; int manageDSAit = get_manageDSAit( op ); struct berval *newSuperior = op->oq_modrdn.rs_newSup; Debug( LDAP_DEBUG_TRACE, "==>backsql_modrdn() renaming entry \"%s\", " "newrdn=\"%s\", newSuperior=\"%s\"\n", op->o_req_dn.bv_val, op->oq_modrdn.rs_newrdn.bv_val, newSuperior ? newSuperior->bv_val : "(NULL)" ); rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "could not get connection handle - exiting\n" ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; e = NULL; goto done; } bsi.bsi_e = &r; rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY | BACKSQL_ISF_GET_OC ) ); switch ( rs->sr_err ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } e = &r; /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve modrdnDN ID - no such entry\n" ); if ( !BER_BVISNULL( &r.e_nname ) ) { /* FIXME: should always be true! */ e = &r; } else { e = NULL; } goto done; } Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): entry id=" BACKSQL_IDFMT "\n", BACKSQL_IDARG(e_id.eid_id) ); if ( get_assert( op ) && ( test_filter( op, &r, get_assertion( op ) ) != LDAP_COMPARE_TRUE ) ) { rs->sr_err = LDAP_ASSERTION_FAILED; e = &r; goto done; } if ( backsql_has_children( op, dbh, &op->o_req_ndn ) == LDAP_COMPARE_TRUE ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "entry \"%s\" has children\n", op->o_req_dn.bv_val ); rs->sr_err = LDAP_NOT_ALLOWED_ON_NONLEAF; rs->sr_text = "subtree rename not supported"; e = &r; goto done; } /* * Check for entry access to target */ if ( !access_allowed( op, &r, slap_schema.si_ad_entry, NULL, ACL_WRITE, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " no access to entry\n" ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto done; } dnParent( &op->o_req_dn, &pdn ); dnParent( &op->o_req_ndn, &pndn ); /* * namingContext "" is not supported */ if ( BER_BVISEMPTY( &pdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "parent is \"\" - aborting\n" ); rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "not allowed within namingContext"; e = NULL; goto done; } /* * Check for children access to parent */ bsi.bsi_e = &p; e_id = bsi.bsi_base_id; memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) ); rs->sr_err = backsql_init_search( &bsi, &pndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, BACKSQL_ISF_GET_ENTRY ); Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): old parent entry id is " BACKSQL_IDFMT "\n", BACKSQL_IDARG(bsi.bsi_base_id.eid_id) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve renameDN ID - no such entry\n" ); e = &p; goto done; } if ( !access_allowed( op, &p, slap_schema.si_ad_children, NULL, newSuperior ? ACL_WDEL : ACL_WRITE, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " no access to parent\n" ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto done; } if ( newSuperior ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); /* * namingContext "" is not supported */ if ( BER_BVISEMPTY( newSuperior ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "newSuperior is \"\" - aborting\n" ); rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "not allowed within namingContext"; e = NULL; goto done; } new_pdn = newSuperior; new_npdn = op->oq_modrdn.rs_nnewSup; /* * Check for children access to new parent */ bsi.bsi_e = &n; rs->sr_err = backsql_init_search( &bsi, new_npdn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve renameDN ID - no such entry\n" ); e = &n; goto done; } n_id = bsi.bsi_base_id; Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new parent entry id=" BACKSQL_IDFMT "\n", BACKSQL_IDARG(n_id.eid_id) ); if ( !access_allowed( op, &n, slap_schema.si_ad_children, NULL, ACL_WADD, NULL ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "no access to new parent \"%s\"\n", new_pdn->bv_val ); rs->sr_err = LDAP_INSUFFICIENT_ACCESS; e = &n; goto done; } } else { n_id = bsi.bsi_base_id; new_pdn = &pdn; new_npdn = &pndn; } memset( &bsi.bsi_base_id, 0, sizeof( bsi.bsi_base_id ) ); if ( newSuperior && dn_match( &pndn, new_npdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "newSuperior is equal to old parent - ignored\n" ); newSuperior = NULL; } if ( newSuperior && dn_match( &op->o_req_ndn, new_npdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "newSuperior is equal to entry being moved " "- aborting\n" ); rs->sr_err = LDAP_OTHER; rs->sr_text = "newSuperior is equal to old DN"; e = &r; goto done; } build_new_dn( &new_dn, new_pdn, &op->oq_modrdn.rs_newrdn, op->o_tmpmemctx ); build_new_dn( &new_ndn, new_npdn, &op->oq_modrdn.rs_nnewrdn, op->o_tmpmemctx ); Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n", new_dn.bv_val ); realnew_dn = new_dn; if ( backsql_api_dn2odbc( op, rs, &realnew_dn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): " "backsql_api_dn2odbc(\"%s\") failed\n", op->o_req_dn.bv_val, realnew_dn.bv_val ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "executing renentry_stmt\n" ); rc = backsql_Prepare( dbh, &sth, bi->sql_renentry_stmt, 0 ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "error preparing renentry_stmt\n" ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &realnew_dn ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "error binding DN parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamID( sth, 2, SQL_PARAM_INPUT, &n_id.eid_id ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "error binding parent ID parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamID( sth, 3, SQL_PARAM_INPUT, &e_id.eid_keyval ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "error binding entry ID parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = backsql_BindParamID( sth, 4, SQL_PARAM_INPUT, &e_id.eid_id ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "error binding ID parameter for objectClass %s\n", oc->bom_oc->soc_cname.bv_val ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_text = "SQL-backend error"; rs->sr_err = LDAP_OTHER; e = NULL; goto done; } rc = SQLExecute( sth ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " "could not rename ldap_entries record\n" ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; e = NULL; goto done; } SQLFreeStmt( sth, SQL_DROP ); assert( op->orr_modlist != NULL ); slap_mods_opattrs( op, &op->orr_modlist, 1 ); assert( e_id.eid_oc != NULL ); oc = e_id.eid_oc; rs->sr_err = backsql_modify_internal( op, rs, dbh, oc, &e_id, op->orr_modlist ); slap_graduate_commit_csn( op ); if ( rs->sr_err != LDAP_SUCCESS ) { e = &r; goto done; } if ( BACKSQL_CHECK_SCHEMA( bi ) ) { char textbuf[ SLAP_TEXT_BUFLEN ] = { '\0' }; backsql_entry_clean( op, &r ); (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); bsi.bsi_e = &r; rs->sr_err = backsql_init_search( &bsi, &new_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, slap_anlist_all_attributes, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) ); switch ( rs->sr_err ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &new_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } e = &r; /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_modrdn(): " "could not retrieve modrdnDN ID - no such entry\n" ); if ( !BER_BVISNULL( &r.e_nname ) ) { /* FIXME: should always be true! */ e = &r; } else { e = NULL; } goto done; } e_id = bsi.bsi_base_id; rs->sr_err = entry_schema_check( op, &r, NULL, 0, 0, NULL, &rs->sr_text, textbuf, sizeof( textbuf ) ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(\"%s\"): " "entry failed schema check -- aborting\n", r.e_name.bv_val ); e = NULL; goto done; } } done:; if ( e != NULL ) { if ( !access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } } } /* * Commit only if all operations succeed */ if ( sth != SQL_NULL_HSTMT ) { SQLUSMALLINT CompletionType = SQL_ROLLBACK; if ( rs->sr_err == LDAP_SUCCESS && !op->o_noop ) { CompletionType = SQL_COMMIT; } SQLTransact( SQL_NULL_HENV, dbh, CompletionType ); } if ( op->o_noop && rs->sr_err == LDAP_SUCCESS ) { rs->sr_err = LDAP_X_NO_OPERATION; } send_ldap_result( op, rs ); slap_graduate_commit_csn( op ); if ( !BER_BVISNULL( &realnew_dn ) && realnew_dn.bv_val != new_dn.bv_val ) { ch_free( realnew_dn.bv_val ); } if ( !BER_BVISNULL( &new_dn ) ) { slap_sl_free( new_dn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &new_ndn ) ) { slap_sl_free( new_ndn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &e_id.eid_ndn ) ) { (void)backsql_free_entryID( &e_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &n_id.eid_ndn ) ) { (void)backsql_free_entryID( &n_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &r.e_nname ) ) { backsql_entry_clean( op, &r ); } if ( !BER_BVISNULL( &p.e_nname ) ) { backsql_entry_clean( op, &p ); } if ( !BER_BVISNULL( &n.e_nname ) ) { backsql_entry_clean( op, &n ); } if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } Debug( LDAP_DEBUG_TRACE, "<==backsql_modrdn()\n" ); return rs->sr_err; }
int backsql_operational( Operation *op, SlapReply *rs ) { backsql_info *bi = (backsql_info*)op->o_bd->be_private; SQLHDBC dbh = SQL_NULL_HDBC; int rc = 0; Attribute **ap; enum { BACKSQL_OP_HASSUBORDINATES = 0, BACKSQL_OP_ENTRYUUID, BACKSQL_OP_ENTRYCSN, BACKSQL_OP_LAST }; int get_conn = BACKSQL_OP_LAST, got[ BACKSQL_OP_LAST ] = { 0 }; Debug( LDAP_DEBUG_TRACE, "==>backsql_operational(): entry \"%s\"\n", rs->sr_entry->e_nname.bv_val, 0, 0 ); for ( ap = &rs->sr_entry->e_attrs; *ap; ap = &(*ap)->a_next ) { if ( (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) { get_conn--; got[ BACKSQL_OP_HASSUBORDINATES ] = 1; } else if ( (*ap)->a_desc == slap_schema.si_ad_entryUUID ) { get_conn--; got[ BACKSQL_OP_ENTRYUUID ] = 1; } else if ( (*ap)->a_desc == slap_schema.si_ad_entryCSN ) { get_conn--; got[ BACKSQL_OP_ENTRYCSN ] = 1; } } for ( ap = &rs->sr_operational_attrs; *ap; ap = &(*ap)->a_next ) { if ( !got[ BACKSQL_OP_HASSUBORDINATES ] && (*ap)->a_desc == slap_schema.si_ad_hasSubordinates ) { get_conn--; got[ BACKSQL_OP_HASSUBORDINATES ] = 1; } else if ( !got[ BACKSQL_OP_ENTRYUUID ] && (*ap)->a_desc == slap_schema.si_ad_entryUUID ) { get_conn--; got[ BACKSQL_OP_ENTRYUUID ] = 1; } else if ( !got[ BACKSQL_OP_ENTRYCSN ] && (*ap)->a_desc == slap_schema.si_ad_entryCSN ) { get_conn--; got[ BACKSQL_OP_ENTRYCSN ] = 1; } } if ( !get_conn ) { return 0; } rc = backsql_get_db_conn( op, &dbh ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_operational(): " "could not get connection handle - exiting\n", 0, 0, 0 ); return 1; } if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_hasSubordinates, rs->sr_attrs ) ) && !got[ BACKSQL_OP_HASSUBORDINATES ] && attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL ) { rc = backsql_has_children( op, dbh, &rs->sr_entry->e_nname ); switch( rc ) { case LDAP_COMPARE_TRUE: case LDAP_COMPARE_FALSE: *ap = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE ); assert( *ap != NULL ); ap = &(*ap)->a_next; rc = 0; break; default: Debug( LDAP_DEBUG_TRACE, "backsql_operational(): " "has_children failed( %d)\n", rc, 0, 0 ); return 1; } } if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryUUID, rs->sr_attrs ) ) && !got[ BACKSQL_OP_ENTRYUUID ] && attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryUUID ) == NULL ) { backsql_srch_info bsi = { 0 }; rc = backsql_init_search( &bsi, &rs->sr_entry->e_nname, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, NULL, BACKSQL_ISF_GET_ID ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_operational(): " "could not retrieve entry ID - no such entry\n", 0, 0, 0 ); return 1; } *ap = backsql_operational_entryUUID( bi, &bsi.bsi_base_id ); (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } if ( *ap == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_operational(): " "could not retrieve entryUUID\n", 0, 0, 0 ); return 1; } ap = &(*ap)->a_next; } if ( ( SLAP_OPATTRS( rs->sr_attr_flags ) || ad_inlist( slap_schema.si_ad_entryCSN, rs->sr_attrs ) ) && !got[ BACKSQL_OP_ENTRYCSN ] && attr_find( rs->sr_entry->e_attrs, slap_schema.si_ad_entryCSN ) == NULL ) { *ap = backsql_operational_entryCSN( op ); if ( *ap == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_operational(): " "could not retrieve entryCSN\n", 0, 0, 0 ); return 1; } ap = &(*ap)->a_next; } Debug( LDAP_DEBUG_TRACE, "<==backsql_operational(%d)\n", rc, 0, 0); return rc; }
int backsql_compare( Operation *op, SlapReply *rs ) { SQLHDBC dbh = SQL_NULL_HDBC; Entry e = { 0 }; Attribute *a = NULL; backsql_srch_info bsi = { 0 }; int rc; int manageDSAit = get_manageDSAit( op ); AttributeName anlist[2]; Debug( LDAP_DEBUG_TRACE, "==>backsql_compare()\n", 0, 0, 0 ); rs->sr_err = backsql_get_db_conn( op, &dbh ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_compare(): " "could not get connection handle - exiting\n", 0, 0, 0 ); rs->sr_text = ( rs->sr_err == LDAP_OTHER ) ? "SQL-backend error" : NULL; goto return_results; } anlist[ 0 ].an_name = op->oq_compare.rs_ava->aa_desc->ad_cname; anlist[ 0 ].an_desc = op->oq_compare.rs_ava->aa_desc; BER_BVZERO( &anlist[ 1 ].an_name ); /* * Get the entry */ bsi.bsi_e = &e; rc = backsql_init_search( &bsi, &op->o_req_ndn, LDAP_SCOPE_BASE, (time_t)(-1), NULL, dbh, op, rs, anlist, ( BACKSQL_ISF_MATCHED | BACKSQL_ISF_GET_ENTRY ) ); switch ( rc ) { case LDAP_SUCCESS: break; case LDAP_REFERRAL: if ( manageDSAit && !BER_BVISNULL( &bsi.bsi_e->e_nname ) && dn_match( &op->o_req_ndn, &bsi.bsi_e->e_nname ) ) { rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; rs->sr_matched = NULL; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } break; } /* fallthru */ default: Debug( LDAP_DEBUG_TRACE, "backsql_compare(): " "could not retrieve compareDN ID - no such entry\n", 0, 0, 0 ); goto return_results; } if ( get_assert( op ) && ( test_filter( op, &e, get_assertion( op ) ) != LDAP_COMPARE_TRUE ) ) { rs->sr_err = LDAP_ASSERTION_FAILED; goto return_results; } if ( is_at_operational( op->oq_compare.rs_ava->aa_desc->ad_type ) ) { SlapReply nrs = { REP_SEARCH }; Attribute **ap; for ( ap = &e.e_attrs; *ap; ap = &(*ap)->a_next ) ; nrs.sr_attrs = anlist; nrs.sr_entry = &e; nrs.sr_attr_flags = SLAP_OPATTRS_NO; nrs.sr_operational_attrs = NULL; rs->sr_err = backsql_operational( op, &nrs ); if ( rs->sr_err != LDAP_SUCCESS ) { goto return_results; } *ap = nrs.sr_operational_attrs; } if ( ! access_allowed( op, &e, op->oq_compare.rs_ava->aa_desc, &op->oq_compare.rs_ava->aa_value, ACL_COMPARE, NULL ) ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; goto return_results; } rs->sr_err = LDAP_NO_SUCH_ATTRIBUTE; for ( a = attrs_find( e.e_attrs, op->oq_compare.rs_ava->aa_desc ); a != NULL; a = attrs_find( a->a_next, op->oq_compare.rs_ava->aa_desc ) ) { rs->sr_err = LDAP_COMPARE_FALSE; if ( attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, &op->oq_compare.rs_ava->aa_value, NULL, op->o_tmpmemctx ) == 0 ) { rs->sr_err = LDAP_COMPARE_TRUE; break; } } return_results:; switch ( rs->sr_err ) { case LDAP_COMPARE_TRUE: case LDAP_COMPARE_FALSE: break; default: if ( !BER_BVISNULL( &e.e_nname ) && ! access_allowed( op, &e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = NULL; } break; } send_ldap_result( op, rs ); if ( rs->sr_matched ) { rs->sr_matched = NULL; } if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &e.e_nname ) ) { backsql_entry_clean( op, &e ); } if ( bsi.bsi_attrs != NULL ) { op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } Debug(LDAP_DEBUG_TRACE,"<==backsql_compare()\n",0,0,0); switch ( rs->sr_err ) { case LDAP_COMPARE_TRUE: case LDAP_COMPARE_FALSE: return LDAP_SUCCESS; default: 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; }
int backsql_db_open( BackendDB *bd ) { backsql_info *si = (backsql_info*)bd->be_private; Connection tmp; SQLHDBC dbh; ber_len_t idq_len; struct berval bv; Debug( LDAP_DEBUG_TRACE, "==>backsql_db_open(): " "testing RDBMS connection\n", 0, 0, 0 ); if ( si->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 ( si->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, &si->concat_func, 2 ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "unable to parse pattern '%s'", backsql_def_concat_func, 0, 0 ); return 1; } } /* * Prepare cast string as required */ if ( si->upper_func.bv_val ) { char buf[1024]; if ( BACKSQL_UPPER_NEEDS_CAST( si ) ) { snprintf( buf, sizeof( buf ), "%s(cast (" /* ? as varchar(%d))) */ , si->upper_func.bv_val ); ber_str2bv( buf, 0, 1, &si->upper_func_open ); snprintf( buf, sizeof( buf ), /* (cast(? */ " as varchar(%d)))", BACKSQL_MAX_DN_LEN ); ber_str2bv( buf, 0, 1, &si->upper_func_close ); } else { snprintf( buf, sizeof( buf ), "%s(" /* ?) */ , si->upper_func.bv_val ); ber_str2bv( buf, 0, 1, &si->upper_func_open ); ber_str2bv( /* (? */ ")", 0, 1, &si->upper_func_close ); } } if ( si->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 ( si->subtree_cond.bv_val == NULL ) { /* * Prepare concat function for subtree search condition */ struct berval concat; ber_len_t len = 0; struct berval values[] = { { sizeof( "'%'" ) - 1, "'%'" }, { sizeof( "?" ) - 1, "?" }, { 0, NULL } }; if ( backsql_prepare_pattern( si->concat_func, values, &concat ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "unable to prepare CONCAT pattern", 0, 0, 0 ); return 1; } Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "subtree search SQL condition not specified " "(use \"subtree_cond\" directive in slapd.conf)\n", 0, 0, 0); si->subtree_cond.bv_val = NULL; si->subtree_cond.bv_len = 0; if ( si->upper_func.bv_val ) { /* * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%',?)) */ backsql_strfcat( &si->subtree_cond, &len, "blbbb", &si->upper_func, (ber_len_t)sizeof( "(ldap_entries.dn) LIKE " ) - 1, "(ldap_entries.dn) LIKE ", &si->upper_func_open, &concat, &si->upper_func_close ); } else { /* * ldap_entries.dn LIKE CONCAT('%',?) */ backsql_strfcat( &si->subtree_cond, &len, "lb", (ber_len_t)sizeof( "ldap_entries.dn LIKE " ) - 1, "ldap_entries.dn LIKE ", &concat ); } Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting '%s' as default\n", si->subtree_cond.bv_val, 0, 0 ); } if ( si->children_cond.bv_val == NULL ) { ber_len_t len = 0; if ( si->upper_func.bv_val ) { /* * UPPER(ldap_entries.dn) LIKE UPPER(CONCAT('%,',?)) */ backsql_strfcat( &si->children_cond, &len, "blbl", &si->upper_func, (ber_len_t)sizeof( "(ldap_entries.dn)=" ) - 1, "(ldap_entries.dn)=", &si->upper_func, (ber_len_t)sizeof( "(?)" ) - 1, "(?)" ); } else { /* * ldap_entries.dn LIKE CONCAT('%,',?) */ backsql_strfcat( &si->children_cond, &len, "l", (ber_len_t)sizeof( "ldap_entries.dn=?" ) - 1, "ldap_entries.dn=?"); } Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting '%s' as default\n", si->children_cond.bv_val, 0, 0 ); } if ( si->oc_query == NULL ) { if ( BACKSQL_CREATE_NEEDS_SELECT( si ) ) { si->oc_query = ch_strdup( backsql_def_needs_select_oc_query ); } else { si->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", si->oc_query, 0, 0 ); } if ( si->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 ); si->at_query = ch_strdup( backsql_def_at_query ); } if ( si->insentry_query == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "entry insertion SQL statement not specified " "(use \"insentry_query\" directive in slapd.conf)\n", 0, 0, 0 ); Debug(LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting '%s' by default\n", backsql_def_insentry_query, 0, 0 ); si->insentry_query = ch_strdup( backsql_def_insentry_query ); } if ( si->delentry_query == NULL ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "entry deletion SQL statement not specified " "(use \"delentry_query\" directive in slapd.conf)\n", 0, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "setting '%s' by default\n", backsql_def_delentry_query, 0, 0 ); si->delentry_query = ch_strdup( backsql_def_delentry_query ); } tmp.c_connid =- 1; if ( backsql_get_db_conn( bd, &tmp, &dbh ) != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "connection failed, exiting\n", 0, 0, 0 ); return 1; } /* * Prepare ID selection query */ si->id_query = NULL; idq_len = 0; bv.bv_val = NULL; bv.bv_len = 0; if ( si->upper_func.bv_val == NULL ) { backsql_strcat( &bv, &idq_len, backsql_id_query, "dn=?", NULL ); } else { if ( BACKSQL_HAS_LDAPINFO_DN_RU( si ) ) { backsql_strcat( &bv, &idq_len, backsql_id_query, "dn_ru=?", NULL ); } else { if ( BACKSQL_USE_REVERSE_DN( si ) ) { backsql_strfcat( &bv, &idq_len, "sbl", backsql_id_query, &si->upper_func, (ber_len_t)sizeof( "(dn)=?" ) - 1, "(dn)=?" ); } else { backsql_strfcat( &bv, &idq_len, "sblbcb", backsql_id_query, &si->upper_func, (ber_len_t)sizeof( "(dn)=" ) - 1, "(dn)=", &si->upper_func_open, '?', &si->upper_func_close ); } } } si->id_query = bv.bv_val; /* * Prepare children ID selection query */ si->has_children_query = NULL; idq_len = 0; bv.bv_val = NULL; bv.bv_len = 0; backsql_strfcat( &bv, &idq_len, "sb", "SELECT COUNT(distinct subordinates.id) FROM ldap_entries,ldap_entries AS subordinates WHERE subordinates.parent=ldap_entries.id AND ", &si->children_cond ); si->has_children_query = bv.bv_val; backsql_free_db_conn( bd, &tmp ); if ( !BACKSQL_SCHEMA_LOADED( si ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_db_open(): " "test failed, schema map not loaded - exiting\n", 0, 0, 0 ); return 1; } Debug( LDAP_DEBUG_TRACE, "<==backsql_db_open(): " "test succeeded, schema map loaded\n", 0, 0, 0 ); return 0; }
int backsql_operational( BackendDB *be, Connection *conn, Operation *op, Entry *e, AttributeName *attrs, int opattrs, Attribute **a ) { backsql_info *bi = (backsql_info*)be->be_private; SQLHDBC dbh = SQL_NULL_HDBC; Attribute **aa = a; int rc = 0; Debug( LDAP_DEBUG_TRACE, "==>backsql_operational(): entry '%s'\n", e->e_nname.bv_val, 0, 0 ); if ( ( opattrs || ad_inlist( slap_schema.si_ad_hasSubordinates, attrs ) ) && attr_find( e->e_attrs, slap_schema.si_ad_hasSubordinates ) == NULL ) { rc = backsql_get_db_conn( be, conn, &dbh ); if ( rc != LDAP_SUCCESS ) { goto no_connection; } rc = backsql_has_children( bi, dbh, &e->e_nname ); switch( rc ) { case LDAP_COMPARE_TRUE: case LDAP_COMPARE_FALSE: *aa = slap_operational_hasSubordinate( rc == LDAP_COMPARE_TRUE ); if ( *aa != NULL ) { aa = &(*aa)->a_next; } rc = 0; break; default: Debug(LDAP_DEBUG_TRACE, "backsql_operational(): " "has_children failed( %d)\n", rc, 0, 0 ); rc = 1; break; } } return rc; no_connection:; Debug( LDAP_DEBUG_TRACE, "backsql_operational(): " "could not get connection handle - exiting\n", 0, 0, 0 ); send_ldap_result( conn, op, rc, "", rc == LDAP_OTHER ? "SQL-backend error" : "", NULL, NULL ); return 1; }