From 87a63d3b5db04522acb453eb662587fed6d22696 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sun, 3 Oct 2004 21:08:54 +0000 Subject: [PATCH] improve previous commit; consistently use dn/ndn; add support for LDAP_SCOPE_SUBORDINATE --- servers/slapd/back-sql/add.c | 25 ++++- servers/slapd/back-sql/back-sql.h | 12 ++- servers/slapd/back-sql/bind.c | 16 ++-- servers/slapd/back-sql/compare.c | 16 ++-- servers/slapd/back-sql/delete.c | 1 + servers/slapd/back-sql/entry-id.c | 88 ++++++++++++------ servers/slapd/back-sql/modify.c | 1 + servers/slapd/back-sql/modrdn.c | 5 +- servers/slapd/back-sql/search.c | 146 ++++++++++++++++++++---------- servers/slapd/back-sql/util.c | 2 +- 10 files changed, 211 insertions(+), 101 deletions(-) diff --git a/servers/slapd/back-sql/add.c b/servers/slapd/back-sql/add.c index 8bb4c727e9..19fd90ef72 100644 --- a/servers/slapd/back-sql/add.c +++ b/servers/slapd/back-sql/add.c @@ -752,7 +752,7 @@ backsql_add_attr( * to build the entry */ if ( at->a_desc == slap_schema.si_ad_objectClass ) { - if ( bvmatch( at_val, &oc->bom_oc->soc_cname ) ) + if ( dn_match( at_val, &oc->bom_oc->soc_cname ) ) { continue; } @@ -882,6 +882,7 @@ backsql_add( Operation *op, SlapReply *rs ) *at_objectClass = NULL; struct berval pdn; struct berval realdn = BER_BVNULL, + realndn = BER_BVNULL, realpdn = BER_BVNULL; Debug( LDAP_DEBUG_TRACE, "==>backsql_add(\"%s\")\n", @@ -965,14 +966,23 @@ backsql_add( Operation *op, SlapReply *rs ) if ( backsql_api_dn2odbc( op, rs, &realdn ) ) { Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " "backsql_api_dn2odbc(\"%s\") failed\n", - op->oq_add.rs_e->e_name.bv_val, - op->oq_add.rs_e->e_name.bv_val, 0 ); + op->oq_add.rs_e->e_name.bv_val, realdn.bv_val, 0 ); + rs->sr_err = LDAP_OTHER; + rs->sr_text = "SQL-backend error"; + goto done; + } + + realndn = op->oq_add.rs_e->e_nname; + if ( backsql_api_dn2odbc( op, rs, &realndn ) ) { + Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " + "backsql_api_dn2odbc(\"%s\") failed\n", + op->oq_add.rs_e->e_name.bv_val, realndn.bv_val, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; goto done; } - rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realdn ); + rs->sr_err = backsql_dn2id( bi, NULL, dbh, &realndn ); if ( rs->sr_err == LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_add(\"%s\"): " "entry exists\n", @@ -1388,10 +1398,15 @@ done:; { ch_free( realdn.bv_val ); } + if ( !BER_BVISNULL( &realndn ) + && realndn.bv_val != op->oq_add.rs_e->e_nname.bv_val ) + { + ch_free( realndn.bv_val ); + } if ( !BER_BVISNULL( &realpdn ) && realpdn.bv_val != pdn.bv_val ) { ch_free( realpdn.bv_val ); } - if ( !BER_BVISNULL( &parent_id.eid_dn ) ) { + if ( !BER_BVISNULL( &parent_id.eid_ndn ) ) { (void)backsql_free_entryID( &parent_id, 0 ); } diff --git a/servers/slapd/back-sql/back-sql.h b/servers/slapd/back-sql/back-sql.h index fa74a36d2a..d41ecd0579 100644 --- a/servers/slapd/back-sql/back-sql.h +++ b/servers/slapd/back-sql/back-sql.h @@ -153,13 +153,14 @@ typedef struct backsql_entryID { unsigned long eid_oc_id; struct berval eid_dn; + struct berval eid_ndn; struct backsql_entryID *eid_next; } backsql_entryID; #ifdef BACKSQL_ARBITRARY_KEY -#define BACKSQL_ENTRYID_INIT { BER_BVNULL, BER_BVNULL, 0, BER_BVNULL, NULL } +#define BACKSQL_ENTRYID_INIT { BER_BVNULL, BER_BVNULL, 0, BER_BVNULL, BER_BVNULL, NULL } #else /* ! BACKSQL_ARBITRARY_KEY */ -#define BACKSQL_ENTRYID_INIT { 0, 0, 0, BER_BVNULL, NULL } +#define BACKSQL_ENTRYID_INIT { 0, 0, 0, BER_BVNULL, BER_BVNULL, NULL } #endif /* BACKSQL_ARBITRARY_KEY */ /* @@ -265,9 +266,14 @@ typedef struct backsql_srch_info { #define BSQL_SF_ALL_OPER 0x0001 #define BSQL_SF_FILTER_HASSUBORDINATE 0x0002 - struct berval *bsi_base_dn; + struct berval *bsi_base_ndn; backsql_entryID bsi_base_id; int bsi_scope; +/* BACKSQL_SCOPE_BASE_LIKE can be set by API in ors_scope + * whenever the search base DN contains chars that cannot + * be mapped into the charset used in the RDBMS; so they're + * turned into '%' and an approximate ('LIKE') condition + * is used */ #define BACKSQL_SCOPE_BASE_LIKE ( LDAP_SCOPE_BASE | 0x1000 ) Filter *bsi_filter; int bsi_slimit, diff --git a/servers/slapd/back-sql/bind.c b/servers/slapd/back-sql/bind.c index 836b865fa4..7803776f6b 100644 --- a/servers/slapd/back-sql/bind.c +++ b/servers/slapd/back-sql/bind.c @@ -38,7 +38,7 @@ backsql_bind( Operation *op, SlapReply *rs ) backsql_srch_info bsi; AttributeName anlist[2]; int rc; - struct berval dn; + struct berval ndn; Debug( LDAP_DEBUG_TRACE, "==>backsql_bind()\n", 0, 0, 0 ); @@ -73,8 +73,8 @@ backsql_bind( Operation *op, SlapReply *rs ) return 1; } - dn = op->o_req_ndn; - if ( backsql_api_dn2odbc( op, rs, &dn ) ) { + ndn = op->o_req_ndn; + if ( backsql_api_dn2odbc( op, rs, &ndn ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "backsql_api_dn2odbc failed\n", 0, 0, 0 ); @@ -87,11 +87,11 @@ backsql_bind( Operation *op, SlapReply *rs ) anlist[0].an_desc = password; anlist[1].an_name.bv_val = NULL; - rc = backsql_init_search( &bsi, &dn, LDAP_SCOPE_BASE, + rc = backsql_init_search( &bsi, &ndn, LDAP_SCOPE_BASE, -1, -1, -1, NULL, dbh, op, rs, anlist, 1 ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_bind(): " - "could not retrieve bind dn id - no such entry\n", + "could not retrieve bindDN ID - no such entry\n", 0, 0, 0 ); rs->sr_err = LDAP_INVALID_CREDENTIALS; send_ldap_result( op, rs ); @@ -134,7 +134,7 @@ backsql_bind( Operation *op, SlapReply *rs ) } error_return:; - if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_dn ) ) { + if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0 ); } @@ -143,8 +143,8 @@ error_return:; return 1; } - if ( dn.bv_val != op->o_req_dn.bv_val ) { - ch_free( dn.bv_val ); + if ( ndn.bv_val != op->o_req_ndn.bv_val ) { + ch_free( ndn.bv_val ); } Debug(LDAP_DEBUG_TRACE,"<==backsql_bind()\n",0,0,0); diff --git a/servers/slapd/back-sql/compare.c b/servers/slapd/back-sql/compare.c index ab2a2d0bda..1f64cc749c 100644 --- a/servers/slapd/back-sql/compare.c +++ b/servers/slapd/back-sql/compare.c @@ -37,7 +37,7 @@ backsql_compare( Operation *op, SlapReply *rs ) backsql_srch_info bsi; int rc; AttributeName anlist[2]; - struct berval dn; + struct berval ndn; user_entry.e_name.bv_val = NULL; user_entry.e_name.bv_len = 0; @@ -58,8 +58,8 @@ backsql_compare( Operation *op, SlapReply *rs ) goto return_results; } - dn = op->o_req_ndn; - if ( backsql_api_dn2odbc( op, rs, &dn ) ) { + ndn = op->o_req_ndn; + if ( backsql_api_dn2odbc( op, rs, &ndn ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "backsql_api_dn2odbc failed\n", 0, 0, 0 ); @@ -95,11 +95,11 @@ backsql_compare( Operation *op, SlapReply *rs ) user_entry.e_attrs = nrs.sr_operational_attrs; } else { - rc = backsql_init_search( &bsi, &dn, LDAP_SCOPE_BASE, + rc = backsql_init_search( &bsi, &ndn, LDAP_SCOPE_BASE, -1, -1, -1, NULL, dbh, op, rs, anlist, 1 ); if ( rc != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_compare(): " - "could not retrieve compare dn id - no such entry\n", + "could not retrieve compareDN ID - no such entry\n", 0, 0, 0 ); rs->sr_err = LDAP_NO_SUCH_OBJECT; goto return_results; @@ -145,12 +145,12 @@ backsql_compare( Operation *op, SlapReply *rs ) return_results:; send_ldap_result( op, rs ); - if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_dn ) ) { + if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0 ); } - if ( dn.bv_val != op->o_req_dn.bv_val ) { - ch_free( dn.bv_val ); + if ( ndn.bv_val != op->o_req_ndn.bv_val ) { + ch_free( ndn.bv_val ); } if ( e != NULL ) { diff --git a/servers/slapd/back-sql/delete.c b/servers/slapd/back-sql/delete.c index 5cf9b6456e..f9e14f0cad 100644 --- a/servers/slapd/back-sql/delete.c +++ b/servers/slapd/back-sql/delete.c @@ -120,6 +120,7 @@ backsql_delete( Operation *op, SlapReply *rs ) goto done; } + /* FIXME: API... */ rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_delete(): " diff --git a/servers/slapd/back-sql/entry-id.c b/servers/slapd/back-sql/entry-id.c index 13d9840dbb..1153bd0ec7 100644 --- a/servers/slapd/back-sql/entry-id.c +++ b/servers/slapd/back-sql/entry-id.c @@ -42,9 +42,16 @@ backsql_free_entryID( backsql_entryID *id, int freeit ) next = id->eid_next; - if ( id->eid_dn.bv_val != NULL ) { - free( id->eid_dn.bv_val ); - BER_BVZERO( &id->eid_dn ); + if ( !BER_BVISNULL( &id->eid_ndn ) ) { + if ( !BER_BVISNULL( &id->eid_dn ) + && id->eid_dn.bv_val != id->eid_ndn.bv_val ) + { + free( id->eid_dn.bv_val ); + BER_BVZERO( &id->eid_dn ); + } + + free( id->eid_ndn.bv_val ); + BER_BVZERO( &id->eid_ndn ); } #ifdef BACKSQL_ARBITRARY_KEY @@ -66,12 +73,15 @@ backsql_free_entryID( backsql_entryID *id, int freeit ) return next; } +/* + * NOTE: the dn must be normalized + */ int backsql_dn2id( backsql_info *bi, backsql_entryID *id, SQLHDBC dbh, - struct berval *dn ) + struct berval *ndn ) { SQLHSTMT sth; BACKSQL_ROW_NTS row; @@ -80,7 +90,7 @@ backsql_dn2id( /* TimesTen */ char upperdn[ BACKSQL_MAX_DN_LEN + 1 ]; - struct berval toBind; + struct berval tbbDN; int i, j; /* @@ -91,18 +101,18 @@ backsql_dn2id( */ Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): dn=\"%s\"%s\n", - dn->bv_val, id == NULL ? " (no ID)" : "", 0 ); + ndn->bv_val, id == NULL ? " (no ID)" : "", 0 ); - if ( dn->bv_len > BACKSQL_MAX_DN_LEN ) { + if ( ndn->bv_len > BACKSQL_MAX_DN_LEN ) { Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): DN \"%s\" (%ld bytes) " "exceeds max DN length (%d):\n", - dn->bv_val, dn->bv_len, BACKSQL_MAX_DN_LEN ); + ndn->bv_val, ndn->bv_len, BACKSQL_MAX_DN_LEN ); return LDAP_OTHER; } /* return baseObject if available and matches */ - if ( bi->sql_baseObject != NULL && bvmatch( dn, &bi->sql_baseObject->e_nname ) ) { + if ( bi->sql_baseObject != NULL && dn_match( ndn, &bi->sql_baseObject->e_nname ) ) { if ( id != NULL ) { #ifdef BACKSQL_ARBITRARY_KEY ber_dupbv( &id->eid_id, &backsql_baseObject_bv ); @@ -113,7 +123,8 @@ backsql_dn2id( #endif /* ! BACKSQL_ARBITRARY_KEY */ id->eid_oc_id = BACKSQL_BASEOBJECT_OC; - ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_nname ); + ber_dupbv( &id->eid_ndn, &bi->sql_baseObject->e_nname ); + ber_dupbv( &id->eid_dn, &bi->sql_baseObject->e_name ); id->eid_next = NULL; } @@ -140,36 +151,36 @@ backsql_dn2id( * that can be searched using indexes */ - for ( i = 0, j = dn->bv_len - 1; dn->bv_val[ i ]; i++, j--) { - upperdn[ i ] = dn->bv_val[ j ]; + for ( i = 0, j = ndn->bv_len - 1; ndn->bv_val[ i ]; i++, j--) { + upperdn[ i ] = ndn->bv_val[ j ]; } upperdn[ i ] = '\0'; ldap_pvt_str2upper( upperdn ); Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn=\"%s\"\n", upperdn, 0, 0 ); - ber_str2bv( upperdn, 0, 0, &toBind ); + ber_str2bv( upperdn, 0, 0, &tbbDN ); } else { if ( BACKSQL_USE_REVERSE_DN( bi ) ) { - AC_MEMCPY( upperdn, dn->bv_val, dn->bv_len + 1 ); + AC_MEMCPY( upperdn, ndn->bv_val, ndn->bv_len + 1 ); ldap_pvt_str2upper( upperdn ); Debug( LDAP_DEBUG_TRACE, "==>backsql_dn2id(): upperdn=\"%s\"\n", upperdn, 0, 0 ); - ber_str2bv( upperdn, 0, 0, &toBind ); + ber_str2bv( upperdn, 0, 0, &tbbDN ); } else { - toBind = *dn; + tbbDN = *ndn; } } - rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &toBind ); + rc = backsql_BindParamBerVal( sth, 1, SQL_PARAM_INPUT, &tbbDN ); if ( rc != SQL_SUCCESS) { /* end TimesTen */ Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): " "error binding dn=\"%s\" parameter:\n", - toBind.bv_val, 0, 0 ); + tbbDN.bv_val, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); return LDAP_OTHER; @@ -179,7 +190,7 @@ backsql_dn2id( if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_dn2id(): " "error executing query (\"%s\", \"%s\"):\n", - bi->sql_id_query, toBind.bv_val, 0 ); + bi->sql_id_query, tbbDN.bv_val, 0 ); backsql_PrintErrors( bi->sql_db_env, dbh, sth, rc ); SQLFreeStmt( sth, SQL_DROP ); return LDAP_OTHER; @@ -188,11 +199,21 @@ backsql_dn2id( backsql_BindRowAsStrings( sth, &row ); rc = SQLFetch( sth ); if ( BACKSQL_SUCCESS( rc ) ) { - res = LDAP_SUCCESS; - Debug( LDAP_DEBUG_TRACE, "<==backsql_dn2id(): id=%s keyval=%s oc_id=%s\n", - row.cols[ 0 ], row.cols[ 1 ], row.cols[ 2 ] ); + char buf[BUFSIZ]; +#ifdef LDAP_DEBUG + snprintf( buf, sizeof(buf), + "id=%s keyval=%s oc_id=%s dn=%s", + row.cols[ 0 ], row.cols[ 1 ], + row.cols[ 2 ], row.cols[ 3 ] ); + Debug( LDAP_DEBUG_TRACE, + "<==backsql_dn2id(): %s\n", buf, 0, 0 ); +#endif /* LDAP_DEBUG */ + + res = LDAP_SUCCESS; if ( id != NULL ) { + struct berval dn; + #ifdef BACKSQL_ARBITRARY_KEY ber_str2bv( row.cols[ 0 ], 0, 1, &id->eid_id ); ber_str2bv( row.cols[ 1 ], 0, 1, &id->eid_keyval ); @@ -202,7 +223,20 @@ backsql_dn2id( #endif /* ! BACKSQL_ARBITRARY_KEY */ id->eid_oc_id = strtol( row.cols[ 2 ], NULL, 0 ); - ber_dupbv( &id->eid_dn, dn ); + ber_str2bv( row.cols[ 3 ], 0, 0, &dn ); + + res = dnPrettyNormal( NULL, &dn, &id->eid_dn, &id->eid_ndn, NULL ); + if ( res != LDAP_SUCCESS ) { + Debug( LDAP_DEBUG_TRACE, + "<==backsql_dn2id(\"%s\"): " + "dnPrettyNormal failed (%d: %s)\n", + ndn->bv_val, res, + ldap_err2string( res ) ); + + /* cleanup... */ + (void)backsql_free_entryID( id, 0 ); + } + id->eid_next = NULL; } @@ -456,12 +490,8 @@ backsql_id2entry( backsql_srch_info *bsi, backsql_entryID *eid ) goto done; } - rc = dnPrettyNormal( NULL, &eid->eid_dn, - &bsi->bsi_e->e_name, &bsi->bsi_e->e_nname, - bsi->bsi_op->o_tmpmemctx ); - if ( rc != LDAP_SUCCESS ) { - return rc; - } + ber_dupbv_x( &bsi->bsi_e->e_name, &eid->eid_dn, bsi->bsi_op->o_tmpmemctx ); + ber_dupbv_x( &bsi->bsi_e->e_nname, &eid->eid_ndn, bsi->bsi_op->o_tmpmemctx ); bsi->bsi_e->e_attrs = NULL; bsi->bsi_e->e_private = NULL; diff --git a/servers/slapd/back-sql/modify.c b/servers/slapd/back-sql/modify.c index 2e43e13c12..168d4cc8bb 100644 --- a/servers/slapd/back-sql/modify.c +++ b/servers/slapd/back-sql/modify.c @@ -61,6 +61,7 @@ backsql_modify( Operation *op, SlapReply *rs ) return 1; } + /* FIXME: API... */ rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modify(): " diff --git a/servers/slapd/back-sql/modrdn.c b/servers/slapd/back-sql/modrdn.c index 5cade96a3c..f57d6e67e4 100644 --- a/servers/slapd/back-sql/modrdn.c +++ b/servers/slapd/back-sql/modrdn.c @@ -65,6 +65,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) return 1; } + /* FIXME: API... */ rs->sr_err = backsql_dn2id( bi, &e_id, dbh, &op->o_req_ndn ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " @@ -191,6 +192,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): new entry dn is \"%s\"\n", new_dn.bv_val, 0, 0 ); + /* FIXME: API... */ rs->sr_err = backsql_dn2id( bi, &pe_id, dbh, &p_ndn ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " @@ -211,6 +213,7 @@ backsql_modrdn( Operation *op, SlapReply *rs ) (void)backsql_free_entryID( &pe_id, 0 ); + /* FIXME: API... */ rs->sr_err = backsql_dn2id( bi, &new_pe_id, dbh, new_npdn ); if ( rs->sr_err != LDAP_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, " backsql_modrdn(): " @@ -450,7 +453,7 @@ modrdn_return:; } } - if ( new_pe_id.eid_dn.bv_val ) { + if ( !BER_BVISNULL( &new_pe_id.eid_ndn ) ) { (void)backsql_free_entryID( &new_pe_id, 0 ); } diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 8e4f594795..2cde0d2b81 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -96,13 +96,15 @@ backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad ) * Initializes the search structure. * * If get_base_id != 0, the field bsi_base_id is filled - * with the entryID of bsi_base_dn; it must be freed + * with the entryID of bsi_base_ndn; it must be freed * by backsql_free_entryID() when no longer required. + * + * NOTE: base must be normalized */ int backsql_init_search( backsql_srch_info *bsi, - struct berval *base, + struct berval *nbase, int scope, int slimit, int tlimit, @@ -117,8 +119,9 @@ backsql_init_search( AttributeName *p; int rc = LDAP_SUCCESS; - bsi->bsi_base_dn = base; + bsi->bsi_base_ndn = nbase; BER_BVZERO( &bsi->bsi_base_id.eid_dn ); + BER_BVZERO( &bsi->bsi_base_id.eid_ndn ); bsi->bsi_scope = scope; bsi->bsi_slimit = slimit; bsi->bsi_tlimit = tlimit; @@ -187,7 +190,7 @@ backsql_init_search( assert( op->o_bd->be_private ); rc = backsql_dn2id( (backsql_info *)op->o_bd->be_private, - &bsi->bsi_base_id, dbh, base ); + &bsi->bsi_base_id, dbh, nbase ); } return ( bsi->bsi_status = rc ); @@ -1109,6 +1112,9 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) "ldap_entries.parent=?" ); break; +#ifdef LDAP_SCOPE_SUBORDINATE + case LDAP_SCOPE_SUBORDINATE: +#endif /* LDAP_SCOPE_SUBORDINATE */ case LDAP_SCOPE_SUBTREE: if ( BACKSQL_CANUPPERCASE( bi ) ) { backsql_strfcat( &bsi->bsi_join_where, "bl", @@ -1184,11 +1190,13 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) int n_candidates = bsi->bsi_n_candidates; /* - * + 1 because we need room for '%'; this makes a subtree + * + 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 temp_base_dn[ BACKSQL_MAX_DN_LEN + 1 + 1 ]; + char tmp_base_ndn[ BACKSQL_MAX_DN_LEN + 1 + 1 ]; bsi->bsi_status = LDAP_SUCCESS; @@ -1271,28 +1279,28 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) * We do not accept DNs longer than BACKSQL_MAX_DN_LEN; * however this should be handled earlier */ - if ( bsi->bsi_base_dn->bv_len > BACKSQL_MAX_DN_LEN ) { + if ( bsi->bsi_base_ndn->bv_len > BACKSQL_MAX_DN_LEN ) { bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } - AC_MEMCPY( temp_base_dn, bsi->bsi_base_dn->bv_val, - bsi->bsi_base_dn->bv_len + 1 ); + 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( temp_base_dn ); + ldap_pvt_str2upper( tmp_base_ndn ); } Debug( LDAP_DEBUG_TRACE, "(base)dn: \"%s\"\n", - temp_base_dn, 0, 0 ); + tmp_base_ndn, 0, 0 ); rc = backsql_BindParamStr( sth, 2, SQL_PARAM_INPUT, - temp_base_dn, BACKSQL_MAX_DN_LEN ); + tmp_base_ndn, BACKSQL_MAX_DN_LEN ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " - "error binding base_dn parameter\n", 0, 0, 0 ); + "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; @@ -1300,12 +1308,16 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) } break; - case LDAP_SCOPE_SUBTREE: { +#ifdef LDAP_SCOPE_SUBORDINATE + case LDAP_SCOPE_SUBORDINATE: +#endif /* LDAP_SCOPE_SUBORDINATE */ + case LDAP_SCOPE_SUBTREE: + { /* * We do not accept DNs longer than BACKSQL_MAX_DN_LEN; * however this should be handled earlier */ - if ( bsi->bsi_base_dn->bv_len > BACKSQL_MAX_DN_LEN ) { + if ( bsi->bsi_base_ndn->bv_len > BACKSQL_MAX_DN_LEN ) { bsi->bsi_status = LDAP_OTHER; return BACKSQL_AVL_CONTINUE; } @@ -1324,34 +1336,59 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) * If "dn_ru" is being used, do a prefix search. */ if ( BACKSQL_HAS_LDAPINFO_DN_RU( bi ) ) { - temp_base_dn[ 0 ] = '\0'; - for ( i = 0, j = bsi->bsi_base_dn->bv_len - 1; + tmp_base_ndn[ 0 ] = '\0'; + + for ( i = 0, j = bsi->bsi_base_ndn->bv_len - 1; j >= 0; i++, j--) { - temp_base_dn[ i ] = bsi->bsi_base_dn->bv_val[ j ]; + tmp_base_ndn[ i ] = bsi->bsi_base_ndn->bv_val[ j ]; } - temp_base_dn[ i ] = '%'; - temp_base_dn[ i + 1 ] = '\0'; + +#ifdef LDAP_SCOPE_SUBORDINATE + if ( bsi->bsi_scope == LDAP_SCOPE_SUBORDINATE ) { + tmp_base_ndn[ i++ ] = ','; + } +#endif /* LDAP_SCOPE_SUBORDINATE */ + + tmp_base_ndn[ i ] = '%'; + tmp_base_ndn[ i + 1 ] = '\0'; } else { - temp_base_dn[ 0 ] = '%'; - AC_MEMCPY( &temp_base_dn[ 1 ], bsi->bsi_base_dn->bv_val, - bsi->bsi_base_dn->bv_len + 1 ); + i = 0; + + tmp_base_ndn[ i++ ] = '%'; + +#ifdef LDAP_SCOPE_SUBORDINATE + if ( bsi->bsi_scope == LDAP_SCOPE_SUBORDINATE ) { + tmp_base_ndn[ i++ ] = ','; + } +#endif /* LDAP_SCOPE_SUBORDINATE */ + + 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( temp_base_dn ); + ldap_pvt_str2upper( tmp_base_ndn ); } - Debug( LDAP_DEBUG_TRACE, "(sub)dn: \"%s\"\n", temp_base_dn, - 0, 0 ); +#ifdef LDAP_SCOPE_SUBORDINATE + if ( bsi->bsi_scope == LDAP_SCOPE_SUBORDINATE ) { + Debug( LDAP_DEBUG_TRACE, "(children)dn: \"%s\"\n", + tmp_base_ndn, 0, 0 ); + } else +#endif /* LDAP_SCOPE_SUBORDINATE */ + { + Debug( LDAP_DEBUG_TRACE, "(sub)dn: \"%s\"\n", + tmp_base_ndn, 0, 0 ); + } rc = backsql_BindParamStr( sth, 2, SQL_PARAM_INPUT, - temp_base_dn, BACKSQL_MAX_DN_LEN ); + tmp_base_ndn, BACKSQL_MAX_DN_LEN ); if ( rc != SQL_SUCCESS ) { Debug( LDAP_DEBUG_TRACE, "backsql_oc_get_candidates(): " - "error binding base_dn parameter (2)\n", + "error binding base_ndn parameter (2)\n", 0, 0, 0 ); backsql_PrintErrors( bi->sql_db_env, bsi->bsi_dbh, sth, rc ); @@ -1362,7 +1399,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) } case LDAP_SCOPE_ONELEVEL: - assert( !BER_BVISNULL( &bsi->bsi_base_id.eid_dn ) ); + assert( !BER_BVISNULL( &bsi->bsi_base_id.eid_ndn ) ); #ifdef BACKSQL_ARBITRARY_KEY Debug( LDAP_DEBUG_TRACE, "(one)id: \"%s\"\n", @@ -1395,7 +1432,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) backsql_BindRowAsStrings( sth, &row ); rc = SQLFetch( sth ); for ( ; BACKSQL_SUCCESS( rc ); rc = SQLFetch( sth ) ) { - struct berval dn, ndn; + struct berval dn, pdn, ndn; backsql_entryID *c_id = NULL; int ret; @@ -1405,7 +1442,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) continue; } - ret = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ); + ret = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL ); if ( dn.bv_val != row.cols[ 3 ] ) { free( dn.bv_val ); } @@ -1414,7 +1451,8 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) continue; } - if ( bi->sql_baseObject && bvmatch( &ndn, &bi->sql_baseObject->e_nname ) ) { + if ( bi->sql_baseObject && dn_match( &ndn, &bi->sql_baseObject->e_nname ) ) { + free( pdn.bv_val ); free( ndn.bv_val ); continue; } @@ -1430,11 +1468,8 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) #endif /* ! BACKSQL_ARBITRARY_KEY */ c_id->eid_oc_id = bsi->bsi_oc->bom_id; - if ( ndn.bv_val == row.cols[ 3 ] ) { - ber_dupbv( &c_id->eid_dn, &ndn ); - } else { - c_id->eid_dn = ndn; - } + c_id->eid_dn = pdn; + c_id->eid_ndn = ndn; /* append at end of list ... */ c_id->eid_next = NULL; @@ -1478,7 +1513,7 @@ backsql_search( Operation *op, SlapReply *rs ) time_t stoptime = 0; backsql_srch_info bsi; backsql_entryID *eid = NULL; - struct berval base; + struct berval nbase = BER_BVNULL; manageDSAit = get_manageDSAit( op ); @@ -1521,19 +1556,19 @@ backsql_search( Operation *op, SlapReply *rs ) /* compute it anyway; root does not use it */ stoptime = op->o_time + op->ors_tlimit; - base = op->o_req_ndn; - if ( backsql_api_dn2odbc( op, rs, &base ) ) { + nbase = op->o_req_ndn; + if ( backsql_api_dn2odbc( op, rs, &nbase ) ) { Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "backsql_api_dn2odbc failed\n", 0, 0, 0 ); rs->sr_err = LDAP_OTHER; rs->sr_text = "SQL-backend error"; send_ldap_result( op, rs ); - return 1; + goto done; } /* init search */ - rs->sr_err = backsql_init_search( &bsi, &base, + rs->sr_err = backsql_init_search( &bsi, &nbase, op->ors_scope, op->ors_slimit, op->ors_tlimit, stoptime, op->ors_filter, @@ -1654,7 +1689,7 @@ backsql_search( Operation *op, SlapReply *rs ) switch ( op->ors_scope ) { case LDAP_SCOPE_BASE: case BACKSQL_SCOPE_BASE_LIKE: - if ( !bvmatch( &e->e_nname, &op->o_req_ndn ) ) { + if ( !dn_match( &e->e_nname, &op->o_req_ndn ) ) { goto next_entry; } break; @@ -1662,6 +1697,7 @@ backsql_search( Operation *op, SlapReply *rs ) case LDAP_SCOPE_ONE: { struct berval rdn = user_entry.e_nname; + rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," ); if ( !dnIsOneLevelRDN( &rdn ) ) { goto next_entry; @@ -1669,7 +1705,17 @@ backsql_search( Operation *op, SlapReply *rs ) /* fall thru */ } +#ifdef LDAP_SCOPE_SUBORDINATE + case LDAP_SCOPE_SUBORDINATE: + /* discard the baseObject entry */ + if ( dn_match( &e->e_nname, &op->o_req_ndn ) ) { + goto next_entry; + } + /* FALLTHRU */ +#endif /* LDAP_SCOPE_SUBORDINATE */ + case LDAP_SCOPE_SUBTREE: + /* FIXME: this should never fail... */ if ( !dnIsSuffix( &e->e_nname, &op->o_req_ndn ) ) { goto next_entry; } @@ -1829,7 +1875,7 @@ end_of_search:; } done:; - if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_dn ) ) { + if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { (void)backsql_free_entryID( &bsi.bsi_base_id, 0 ); } @@ -1837,8 +1883,16 @@ done:; ch_free( bsi.bsi_attrs ); } - if ( base.bv_val != op->o_req_ndn.bv_val ) { - ch_free( base.bv_val ); + if ( !BER_BVISNULL( &nbase ) + && nbase.bv_val != op->o_req_ndn.bv_val ) + { + ch_free( nbase.bv_val ); + } + + /* restore scope ... FIXME: this should be done before ANY + * frontend call that uses op */ + if ( op->ors_scope == BACKSQL_SCOPE_BASE_LIKE ) { + op->ors_scope = LDAP_SCOPE_BASE; } Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 ); diff --git a/servers/slapd/back-sql/util.c b/servers/slapd/back-sql/util.c index 41f099ce18..f198ebedfe 100644 --- a/servers/slapd/back-sql/util.c +++ b/servers/slapd/back-sql/util.c @@ -56,7 +56,7 @@ char backsql_def_delreferrals_query[] = "DELETE FROM ldap_referrals " "WHERE entry_id=?"; char backsql_def_subtree_cond[] = "ldap_entries.dn LIKE CONCAT('%',?)"; char backsql_def_upper_subtree_cond[] = "(ldap_entries.dn) LIKE CONCAT('%',?)"; -char backsql_id_query[] = "SELECT id,keyval,oc_map_id FROM ldap_entries WHERE "; +char backsql_id_query[] = "SELECT id,keyval,oc_map_id,dn FROM ldap_entries WHERE "; /* better ?||? or cast(?||? as varchar) */ char backsql_def_concat_func[] = "CONCAT(?,?)"; -- 2.39.5