📄 search.c
字号:
bsi->bsi_op->o_tmpfree( bsi->bsi_sel.bb_val.bv_val, bsi->bsi_op->o_tmpmemctx ); BER_BVZERO( &bsi->bsi_sel.bb_val ); bsi->bsi_sel.bb_len = 0; bsi->bsi_op->o_tmpfree( bsi->bsi_from.bb_val.bv_val, bsi->bsi_op->o_tmpmemctx ); BER_BVZERO( &bsi->bsi_from.bb_val ); bsi->bsi_from.bb_len = 0; bsi->bsi_op->o_tmpfree( bsi->bsi_join_where.bb_val.bv_val, bsi->bsi_op->o_tmpmemctx ); BER_BVZERO( &bsi->bsi_join_where.bb_val ); bsi->bsi_join_where.bb_len = 0; bsi->bsi_op->o_tmpfree( bsi->bsi_flt_where.bb_val.bv_val, bsi->bsi_op->o_tmpmemctx ); BER_BVZERO( &bsi->bsi_flt_where.bb_val ); bsi->bsi_flt_where.bb_len = 0; Debug( LDAP_DEBUG_TRACE, "<==backsql_srch_query() returns %s\n", query->bv_val ? query->bv_val : "NULL", 0, 0 ); return ( rc <= 0 ? 1 : 0 );}static intbacksql_oc_get_candidates( void *v_oc, void *v_bsi ){ backsql_oc_map_rec *oc = v_oc; backsql_srch_info *bsi = v_bsi; Operation *op = bsi->bsi_op; backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private; struct berval query; SQLHSTMT sth = SQL_NULL_HSTMT; RETCODE rc; int res; BACKSQL_ROW_NTS row; int i; int j; int n_candidates = bsi->bsi_n_candidates; /* * + 1 because we need room for '%'; * + 1 because we need room for ',' for LDAP_SCOPE_SUBORDINATE; * this makes a subtree * search for a DN BACKSQL_MAX_DN_LEN long legal * if it returns that DN only */ char tmp_base_ndn[ BACKSQL_MAX_DN_LEN + 1 + 1 ]; bsi->bsi_status = LDAP_SUCCESS; Debug( LDAP_DEBUG_TRACE, "==>backsql_oc_get_candidates(): oc=\"%s\"\n", BACKSQL_OC_NAME( oc ), 0, 0 ); /* check for abandon */ if ( op->o_abandon ) { bsi->bsi_status = SLAPD_ABANDON; return BACKSQL_AVL_STOP; } if ( bsi->bsi_n_candidates == -1 ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "unchecked limit has been overcome\n", 0, 0, 0 ); /* should never get here */ assert( 0 ); bsi->bsi_status = LDAP_ADMINLIMIT_EXCEEDED; return BACKSQL_AVL_STOP; } bsi->bsi_oc = oc; res = backsql_srch_query( bsi, &query ); if ( res ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error while constructing query for objectclass \"%s\"\n", oc->bom_oc->soc_cname.bv_val, 0, 0 ); /* * FIXME: need to separate errors from legally * impossible filters */ switch ( bsi->bsi_status ) { case LDAP_SUCCESS: case LDAP_UNDEFINED_TYPE: case LDAP_NO_SUCH_OBJECT: /* we are conservative... */ default: bsi->bsi_status = LDAP_SUCCESS; /* try next */ return BACKSQL_AVL_CONTINUE; case LDAP_ADMINLIMIT_EXCEEDED: case LDAP_OTHER: /* don't try any more */ return BACKSQL_AVL_STOP; } } if ( BER_BVISNULL( &query ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "could not construct query for objectclass \"%s\"\n", oc->bom_oc->soc_cname.bv_val, 0, 0 ); bsi->bsi_status = LDAP_SUCCESS; return BACKSQL_AVL_CONTINUE; } Debug( LDAP_DEBUG_TRACE, "Constructed query: %s\n", query.bv_val, 0, 0 ); rc = backsql_Prepare( bsi->bsi_dbh, &sth, query.bv_val, 0 ); bsi->bsi_op->o_tmpfree( query.bv_val, bsi->bsi_op->o_tmpmemctx ); BER_BVZERO( &query ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error preparing query\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } Debug( LDAP_DEBUG_TRACE, "id: '%ld'\n", bsi->bsi_oc->bom_id, 0, 0 ); rc = backsql_BindParamInt( sth, 1, SQL_PARAM_INPUT, &bsi->bsi_oc->bom_id ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error binding objectclass id parameter\n", 0, 0, 0 ); bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } switch ( bsi->bsi_scope ) { case LDAP_SCOPE_BASE: case BACKSQL_SCOPE_BASE_LIKE: /* * We do not accept DNs longer than BACKSQL_MAX_DN_LEN; * however this should be handled earlier */ if ( bsi->bsi_base_ndn->bv_len > BACKSQL_MAX_DN_LEN ) { bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } AC_MEMCPY( tmp_base_ndn, bsi->bsi_base_ndn->bv_val, bsi->bsi_base_ndn->bv_len + 1 ); /* uppercase DN only if the stored DN can be uppercased * for comparison */ if ( BACKSQL_CANUPPERCASE( bi ) ) { ldap_pvt_str2upper( tmp_base_ndn ); } Debug( LDAP_DEBUG_TRACE, "(base)dn: \"%s\"\n", tmp_base_ndn, 0, 0 ); rc = backsql_BindParamStr( sth, 2, SQL_PARAM_INPUT, tmp_base_ndn, BACKSQL_MAX_DN_LEN ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error binding base_ndn parameter\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } break; case LDAP_SCOPE_SUBORDINATE: case LDAP_SCOPE_SUBTREE: { /* if short-cutting the search base, * don't bind any parameter */ if ( bsi->bsi_use_subtree_shortcut ) { break; } /* * We do not accept DNs longer than BACKSQL_MAX_DN_LEN; * however this should be handled earlier */ if ( bsi->bsi_base_ndn->bv_len > BACKSQL_MAX_DN_LEN ) { bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } /* * Sets the parameters for the SQL built earlier * NOTE that all the databases could actually use * the TimesTen version, which would be cleaner * and would also eliminate the need for the * subtree_cond line in the configuration file. * For now, I'm leaving it the way it is, * so non-TimesTen databases use the original code. * But at some point this should get cleaned up. * * If "dn" is being used, do a suffix search. * If "dn_ru" is being used, do a prefix search. */ if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) { tmp_base_ndn[ 0 ] = '\0'; for ( i = 0, j = bsi->bsi_base_ndn->bv_len - 1; j >= 0; i++, j--) { tmp_base_ndn[ i ] = bsi->bsi_base_ndn->bv_val[ j ]; } if ( bsi->bsi_scope == LDAP_SCOPE_SUBORDINATE ) { tmp_base_ndn[ i++ ] = ','; } tmp_base_ndn[ i ] = '%'; tmp_base_ndn[ i + 1 ] = '\0'; } else { i = 0; tmp_base_ndn[ i++ ] = '%'; if ( bsi->bsi_scope == LDAP_SCOPE_SUBORDINATE ) { tmp_base_ndn[ i++ ] = ','; } AC_MEMCPY( &tmp_base_ndn[ i ], bsi->bsi_base_ndn->bv_val, bsi->bsi_base_ndn->bv_len + 1 ); } /* uppercase DN only if the stored DN can be uppercased * for comparison */ if ( BACKSQL_CANUPPERCASE( bi ) ) { ldap_pvt_str2upper( tmp_base_ndn ); } if ( bsi->bsi_scope == LDAP_SCOPE_SUBORDINATE ) { Debug( LDAP_DEBUG_TRACE, "(children)dn: \"%s\"\n", tmp_base_ndn, 0, 0 ); } else { Debug( LDAP_DEBUG_TRACE, "(sub)dn: \"%s\"\n", tmp_base_ndn, 0, 0 ); } rc = backsql_BindParamStr( sth, 2, SQL_PARAM_INPUT, tmp_base_ndn, BACKSQL_MAX_DN_LEN ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error binding base_ndn parameter (2)\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } break; } case LDAP_SCOPE_ONELEVEL: assert( !BER_BVISNULL( &bsi->bsi_base_id.eid_ndn ) );#ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, "(one)id: \"%s\"\n", bsi->bsi_base_id.eid_id.bv_val, 0, 0 );#else /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, "(one)id: '%lu'\n", bsi->bsi_base_id.eid_id, 0, 0 );#endif /* ! BACKSQL_ARBITRARY_KEY */ rc = backsql_BindParamID( sth, 2, SQL_PARAM_INPUT, &bsi->bsi_base_id.eid_id ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error binding base id parameter\n", 0, 0, 0 ); bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } break; } rc = SQLExecute( sth ); if ( !BACKSQL_SUCCESS( rc ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "error executing query\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } backsql_BindRowAsStrings_x( sth, &row, bsi->bsi_op->o_tmpmemctx ); rc = SQLFetch( sth ); for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) { struct berval dn, pdn, ndn; backsql_entryID *c_id = NULL; int ret; ber_str2bv( row.cols[ 3 ], 0, 0, &dn ); if ( backsql_api_odbc2dn( bsi->bsi_op, bsi->bsi_rs, &dn ) ) { continue; } ret = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx ); if ( dn.bv_val != row.cols[ 3 ] ) { free( dn.bv_val ); } if ( ret != LDAP_SUCCESS ) { continue; } if ( bi->sql_baseObject && dn_match( &ndn, &bi->sql_baseObject->e_nname ) ) { goto cleanup; } c_id = (backsql_entryID *)op->o_tmpcalloc( 1, sizeof( backsql_entryID ), op->o_tmpmemctx );#ifdef BACKSQL_ARBITRARY_KEY ber_str2bv_x( row.cols[ 0 ], 0, 1, &c_id->eid_id, op->o_tmpmemctx ); ber_str2bv_x( row.cols[ 1 ], 0, 1, &c_id->eid_keyval, op->o_tmpmemctx );#else /* ! BACKSQL_ARBITRARY_KEY */ if ( lutil_atoulx( &c_id->eid_id, row.cols[ 0 ], 0 ) != 0 ) { goto cleanup; } if ( lutil_atoulx( &c_id->eid_keyval, row.cols[ 1 ], 0 ) != 0 ) { goto cleanup; }#endif /* ! BACKSQL_ARBITRARY_KEY */ c_id->eid_oc_id = bsi->bsi_oc->bom_id; c_id->eid_dn = pdn; c_id->eid_ndn = ndn; /* append at end of list ... */ c_id->eid_next = NULL; *bsi->bsi_id_listtail = c_id; bsi->bsi_id_listtail = &c_id->eid_next;#ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "added entry id=%s, keyval=%s dn=\"%s\"\n", c_id->eid_id.bv_val, c_id->eid_keyval.bv_val, row.cols[ 3 ] );#else /* ! BACKSQL_ARBITRARY_KEY */ Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " "added entry id=%ld, keyval=%ld dn=\"%s\"\n", c_id->eid_id, c_id->eid_keyval, row.cols[ 3 ] );#endif /* ! BACKSQL_ARBITRARY_KEY */ /* count candidates, for unchecked limit */ bsi->bsi_n_candidates--; if ( bsi->bsi_n_candidates == -1 ) { break; } continue;cleanup:; if ( !BER_BVISNULL( &pdn ) ) { op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &ndn ) ) { op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx ); } if ( c_id != NULL ) { ch_free( c_id ); } } backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx ); SQLFreeStmt( sth, SQL_DROP ); Debug( LDAP_DEBUG_TRACE, "<==backsql_oc_get_candidates(): %d\n", n_candidates - bsi->bsi_n_candidates, 0, 0 ); return ( bsi->bsi_n_candidates == -1 ? BACKSQL_AVL_STOP : BACKSQL_AVL_CONTINUE );}intbacksql_search( Operation *op, SlapReply *rs ){ backsql_info *bi = (backsql_info *)op->o_bd->be_private; SQLHDBC dbh = SQL_NULL_HDBC; int sres; Entry user_entry = { 0 }, base_entry = { 0 }; int manageDSAit = get_manageDSAit( op ); time_t stoptime = 0; backsql_srch_info bsi = { 0 }; backsql_entryID *eid = NULL; struct berval nbase = BER_BVNULL; Debug( LDAP_DEBUG_TRACE, "==>backsql_search(): " "base=\"%s\", filter=\"%s\", scope=%d,", op->o_req_ndn.bv_val, op->ors_filterstr.bv_val, op->ors_scope ); Debug( LDAP_DEBUG_TRACE, " deref=%d, attrsonly=%d, " "attributes to load: %s\n", op->ors_deref, op->ors_attrsonly, op->ors_attrs == NULL ? "all" : "custom list" ); if ( op->o_req_ndn.bv_len > BACKSQL_MAX_DN_LEN ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "search base length (%ld) exceeds max length (%d)\n", op->o_req_ndn.bv_len, BACKSQL_MAX_DN_LEN, 0 ); /* * FIXME: a LDAP_NO_SUCH_OBJECT could be appropriate * since it is impossible that such a long DN exists * in the backend */ rs->sr_err = LDAP_ADMINLIMIT_EXCEEDED; send_ldap_result( op, rs ); return 1; } sres = backsql_get_db_conn( op, &dbh ); if ( sres != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "could not get connection handle - exiting\n", 0, 0, 0 ); rs->sr_err = sres; rs->sr_text = sres == LDAP_OTHER ? "SQL-backend error" : NULL; send_ldap_result( op, rs ); return 1; } /* compute it anyway; root does not use it */ stoptime = op->o_time + op->ors_tlimit; /* init search */ bsi.bsi_e = &base_entry; rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, op->ors_scope, stoptime, op->ors_filter, dbh, op, rs, op->ors_attrs, ( 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( &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; } /* an entry was created; free it */ entry_clean( bsi.bsi_e ); /* fall thru */ default:#ifdef SLAP_ACL_HONOR_DISCLOSE if ( !BER_BVISNULL( &base_entry.e_nname ) && !access_allowed( op, &base_entry, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } rs->sr_matched = NULL; rs->sr_text = NULL; }#endif /* SLAP_ACL_HONOR_DISCLOSE */ send_ldap_result( op, rs ); if ( rs->sr_ref ) { ber_bvarray_free( rs->sr_ref ); rs->sr_ref = NULL; } if ( !BER_BVISNULL( &base_entry.e_nname ) ) { entry_clean( &base_entry ); } goto done; }#ifdef SLAP_ACL_HONOR_DISCLOSE /* NOTE: __NEW__ "search" access is required * on searchBase object */ { slap_mask_t mask; if ( get_assert( op ) && ( test_filter( op, &base_entry, get_assertion( op ) ) != LDAP_COMPARE_TRUE ) ) { rs->sr_err = LDAP_ASSERTION_FAILED; } if ( ! access_allowed_mask( op, &base_entry, slap_schema.si_ad_entry, NULL, ACL_SEARCH, NULL, &mask ) ) { if ( rs->sr_err == LDAP_SUCCESS ) { rs->sr_err = LDAP_INSUFFICIENT_ACCESS; } } if ( rs->sr_err != LDAP_SUCCESS ) { if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; rs->sr_text = NULL; } send_ldap_result( op, rs ); goto done; } }#endif /* SLAP_ACL_HONOR_DISCLOSE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -