X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-sql%2Fsearch.c;h=c1ea9952f50bf8243805aebeda74817a9570ffc2;hb=d1824b14ae78b128fb9ff6cf73d2ec4a0e756a90;hp=3097e18fea810fef763ea6d3c75ab1f34b0d9b7c;hpb=edc9b936d051d462a090d46bace7a85db607b4b9;p=openldap diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c index 3097e18fea..c1ea9952f5 100644 --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -1,7 +1,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 1999-2005 The OpenLDAP Foundation. + * Copyright 1999-2006 The OpenLDAP Foundation. * Portions Copyright 1999 Dmitry Kovalev. * Portions Copyright 2002 Pierangelo Masarati. * Portions Copyright 2004 Mark Adamson. @@ -28,6 +28,7 @@ #include "ac/string.h" #include "ac/ctype.h" +#include "lutil.h" #include "slap.h" #include "proto-sql.h" @@ -55,7 +56,7 @@ backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad ) * clear the list (retrieve all attrs) */ if ( ad == NULL ) { - ch_free( bsi->bsi_attrs ); + bsi->bsi_op->o_tmpfree( bsi->bsi_attrs, bsi->bsi_op->o_tmpmemctx ); bsi->bsi_attrs = NULL; bsi->bsi_flags |= BSQL_SF_ALL_ATTRS; return 1; @@ -79,8 +80,9 @@ backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad ) Debug( LDAP_DEBUG_TRACE, "==>backsql_attrlist_add(): " "adding \"%s\" to list\n", ad->ad_cname.bv_val, 0, 0 ); - an = (AttributeName *)ch_realloc( bsi->bsi_attrs, - sizeof( AttributeName ) * ( n_attrs + 2 ) ); + an = (AttributeName *)bsi->bsi_op->o_tmprealloc( bsi->bsi_attrs, + sizeof( AttributeName ) * ( n_attrs + 2 ), + bsi->bsi_op->o_tmpmemctx ); if ( an == NULL ) { return -1; } @@ -108,8 +110,6 @@ backsql_init_search( backsql_srch_info *bsi, struct berval *nbase, int scope, - int slimit, - int tlimit, time_t stoptime, Filter *filter, SQLHDBC dbh, @@ -118,7 +118,7 @@ backsql_init_search( AttributeName *attrs, unsigned flags ) { - AttributeName *p; + backsql_info *bi = (backsql_info *)op->o_bd->be_private; int rc = LDAP_SUCCESS; bsi->bsi_base_ndn = nbase; @@ -126,61 +126,130 @@ backsql_init_search( 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; bsi->bsi_filter = filter; bsi->bsi_dbh = dbh; bsi->bsi_op = op; bsi->bsi_rs = rs; bsi->bsi_flags = BSQL_SF_NONE; - /* - * handle "*" - */ - if ( attrs == NULL ) { - /* also add request for all operational */ - bsi->bsi_attrs = NULL; - bsi->bsi_flags |= BSQL_SF_ALL_USER; + bsi->bsi_attrs = NULL; + + if ( BACKSQL_FETCH_ALL_ATTRS( bi ) ) { + /* + * if requested, simply try to fetch all attributes + */ + bsi->bsi_flags |= BSQL_SF_ALL_ATTRS; } else { - int got_oc = 0; + if ( BACKSQL_FETCH_ALL_USERATTRS( bi ) ) { + bsi->bsi_flags |= BSQL_SF_ALL_USER; - bsi->bsi_attrs = (AttributeName *)ch_calloc( 1, - sizeof( AttributeName ) ); - BER_BVZERO( &bsi->bsi_attrs[ 0 ].an_name ); - - for ( p = attrs; !BER_BVISNULL( &p->an_name ); p++ ) { - /* - * ignore "1.1"; handle "+" - */ - if ( BACKSQL_NCMP( &p->an_name, &AllUser ) == 0 ) { - bsi->bsi_flags |= BSQL_SF_ALL_USER; - continue; + } else if ( BACKSQL_FETCH_ALL_OPATTRS( bi ) ) { + bsi->bsi_flags |= BSQL_SF_ALL_OPER; + } - } else if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0 ) { - bsi->bsi_flags |= BSQL_SF_ALL_OPER; - continue; + if ( attrs == NULL ) { + /* NULL means all user attributes */ + bsi->bsi_flags |= BSQL_SF_ALL_USER; - } else if ( BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) { - continue; + } else { + AttributeName *p; + int got_oc = 0; - } else if ( p->an_desc == slap_schema.si_ad_objectClass ) { - got_oc = 1; + bsi->bsi_attrs = (AttributeName *)bsi->bsi_op->o_tmpalloc( + sizeof( AttributeName ), + bsi->bsi_op->o_tmpmemctx ); + BER_BVZERO( &bsi->bsi_attrs[ 0 ].an_name ); + + for ( p = attrs; !BER_BVISNULL( &p->an_name ); p++ ) { + if ( BACKSQL_NCMP( &p->an_name, &AllUser ) == 0 ) { + /* handle "*" */ + bsi->bsi_flags |= BSQL_SF_ALL_USER; + + /* if all attrs are requested, there's + * no need to continue */ + if ( BSQL_ISF_ALL_ATTRS( bsi ) ) { + bsi->bsi_op->o_tmpfree( bsi->bsi_attrs, + bsi->bsi_op->o_tmpmemctx ); + bsi->bsi_attrs = NULL; + break; + } + continue; + + } else if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0 ) { + /* handle "+" */ + bsi->bsi_flags |= BSQL_SF_ALL_OPER; + + /* if all attrs are requested, there's + * no need to continue */ + if ( BSQL_ISF_ALL_ATTRS( bsi ) ) { + bsi->bsi_op->o_tmpfree( bsi->bsi_attrs, + bsi->bsi_op->o_tmpmemctx ); + bsi->bsi_attrs = NULL; + break; + } + continue; + + } else if ( BACKSQL_NCMP( &p->an_name, &NoAttrs ) == 0 ) { + /* ignore "1.1" */ + continue; + + } else if ( p->an_desc == slap_schema.si_ad_objectClass ) { + got_oc = 1; + } + + backsql_attrlist_add( bsi, p->an_desc ); } - backsql_attrlist_add( bsi, p->an_desc ); + if ( got_oc == 0 && !( bsi->bsi_flags & BSQL_SF_ALL_USER ) ) { + /* add objectClass if not present, + * because it is required to understand + * if an entry is a referral, an alias + * or so... */ + backsql_attrlist_add( bsi, slap_schema.si_ad_objectClass ); + } } - if ( got_oc == 0 ) { - /* add objectClass if not present, - * because it is required to understand - * if an entry is a referral, an alias - * or so... */ - backsql_attrlist_add( bsi, slap_schema.si_ad_objectClass ); + if ( !BSQL_ISF_ALL_ATTRS( bsi ) && bi->sql_anlist ) { + AttributeName *p; + + /* use hints if available */ + for ( p = bi->sql_anlist; !BER_BVISNULL( &p->an_name ); p++ ) { + if ( BACKSQL_NCMP( &p->an_name, &AllUser ) == 0 ) { + /* handle "*" */ + bsi->bsi_flags |= BSQL_SF_ALL_USER; + + /* if all attrs are requested, there's + * no need to continue */ + if ( BSQL_ISF_ALL_ATTRS( bsi ) ) { + bsi->bsi_op->o_tmpfree( bsi->bsi_attrs, + bsi->bsi_op->o_tmpmemctx ); + bsi->bsi_attrs = NULL; + break; + } + continue; + + } else if ( BACKSQL_NCMP( &p->an_name, &AllOper ) == 0 ) { + /* handle "+" */ + bsi->bsi_flags |= BSQL_SF_ALL_OPER; + + /* if all attrs are requested, there's + * no need to continue */ + if ( BSQL_ISF_ALL_ATTRS( bsi ) ) { + bsi->bsi_op->o_tmpfree( bsi->bsi_attrs, + bsi->bsi_op->o_tmpmemctx ); + bsi->bsi_attrs = NULL; + break; + } + continue; + } + + backsql_attrlist_add( bsi, p->an_desc ); + } + } } - bsi->bsi_abandon = 0; bsi->bsi_id_list = NULL; bsi->bsi_id_listtail = &bsi->bsi_id_list; bsi->bsi_n_candidates = 0; @@ -195,13 +264,77 @@ backsql_init_search( bsi->bsi_flt_where.bb_len = 0; bsi->bsi_filter_oc = NULL; - if ( flags & BACKSQL_ISF_GET_ID ) { - assert( op->o_bd->be_private ); + if ( BACKSQL_IS_GET_ID( flags ) ) { + int matched = BACKSQL_IS_MATCHED( flags ); + int getentry = BACKSQL_IS_GET_ENTRY( flags ); + int gotit = 0; + + assert( op->o_bd->be_private != NULL ); + + rc = backsql_dn2id( op, rs, dbh, nbase, &bsi->bsi_base_id, + matched, 1 ); + + /* the entry is collected either if requested for by getentry + * or if get noSuchObject and requested to climb the tree, + * so that a matchedDN or a referral can be returned */ + if ( ( rc == LDAP_NO_SUCH_OBJECT && matched ) || getentry ) { + if ( !BER_BVISNULL( &bsi->bsi_base_id.eid_ndn ) ) { + assert( bsi->bsi_e != NULL ); + + if ( dn_match( nbase, &bsi->bsi_base_id.eid_ndn ) ) + { + gotit = 1; + } + + /* + * let's see if it is a referral and, in case, get it + */ + backsql_attrlist_add( bsi, slap_schema.si_ad_ref ); + rc = backsql_id2entry( bsi, &bsi->bsi_base_id ); + if ( rc == LDAP_SUCCESS ) { + if ( is_entry_referral( bsi->bsi_e ) ) + { + BerVarray erefs = get_entry_referrals( op, bsi->bsi_e ); + if ( erefs ) { + rc = rs->sr_err = LDAP_REFERRAL; + rs->sr_ref = referral_rewrite( erefs, + &bsi->bsi_e->e_nname, + &op->o_req_dn, + scope ); + ber_bvarray_free( erefs ); + + } else { + rc = rs->sr_err = LDAP_OTHER; + rs->sr_text = "bad referral object"; + } + + } else if ( !gotit ) { + rc = rs->sr_err = LDAP_NO_SUCH_OBJECT; + } + } - rc = backsql_dn2id( op, rs, &bsi->bsi_base_id, dbh, nbase, 1 ); + } else { + rs->sr_ref = referral_rewrite( default_referral, + NULL, &op->o_req_dn, scope ); + rc = rs->sr_err = LDAP_REFERRAL; + } + } } - return ( bsi->bsi_status = rc ); + bsi->bsi_status = rc; + + switch ( rc ) { + case LDAP_SUCCESS: + case LDAP_REFERRAL: + break; + + default: + bsi->bsi_op->o_tmpfree( bsi->bsi_attrs, + bsi->bsi_op->o_tmpmemctx ); + break; + } + + return rc; } static int @@ -213,7 +346,8 @@ backsql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op ) return 0; } - backsql_strfcat( &bsi->bsi_flt_where, "c", '(' /* ) */ ); + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, "c", '(' /* ) */ ); while ( 1 ) { res = backsql_process_filter( bsi, f ); @@ -232,20 +366,23 @@ backsql_process_filter_list( backsql_srch_info *bsi, Filter *f, int op ) switch ( op ) { case LDAP_FILTER_AND: - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, "l", (ber_len_t)STRLENOF( " AND " ), " AND " ); break; case LDAP_FILTER_OR: - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, "l", (ber_len_t)STRLENOF( " OR " ), " OR " ); break; } } - backsql_strfcat( &bsi->bsi_flt_where, "c", /* ( */ ')' ); + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, "c", /* ( */ ')' ); return 1; } @@ -350,7 +487,8 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, * SQL filters are more liberal. */ - backsql_strfcat( &bsi->bsi_flt_where, "c", '(' /* ) */ ); + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, "c", '(' /* ) */ ); /* TimesTen */ Debug( LDAP_DEBUG_TRACE, "backsql_process_sub_filter(%s):\n", @@ -363,14 +501,17 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, * If a pre-upper-cased version of the column * or a precompiled upper function exists, use it */ - backsql_strfcat( &bsi->bsi_flt_where, + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, "bl", &at->bam_sel_expr_u, (ber_len_t)STRLENOF( " LIKE '" ), " LIKE '" ); } else { - backsql_strfcat( &bsi->bsi_flt_where, "bl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "bl", &at->bam_sel_expr, (ber_len_t)STRLENOF( " LIKE '" ), " LIKE '" ); } @@ -386,14 +527,18 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, #endif /* BACKSQL_TRACE */ start = bsi->bsi_flt_where.bb_val.bv_len; - backsql_strfcat( &bsi->bsi_flt_where, "b", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "b", &f->f_sub_initial ); if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); } } - backsql_strfcat( &bsi->bsi_flt_where, "c", '%' ); + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "c", '%' ); if ( f->f_sub_any != NULL ) { for ( i = 0; !BER_BVISNULL( &f->f_sub_any[ i ] ); i++ ) { @@ -407,7 +552,8 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, #endif /* BACKSQL_TRACE */ start = bsi->bsi_flt_where.bb_val.bv_len; - backsql_strfcat( &bsi->bsi_flt_where, + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, "bc", &f->f_sub_any[ i ], '%' ); @@ -431,14 +577,18 @@ backsql_process_sub_filter( backsql_srch_info *bsi, Filter *f, #endif /* BACKSQL_TRACE */ start = bsi->bsi_flt_where.bb_val.bv_len; - backsql_strfcat( &bsi->bsi_flt_where, "b", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "b", &f->f_sub_final ); if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); } } - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); return 1; @@ -452,18 +602,21 @@ backsql_merge_from_tbls( backsql_srch_info *bsi, struct berval *from_tbls ) } if ( !BER_BVISNULL( &bsi->bsi_from.bb_val ) ) { - char *start, *end, *tmp; + char *start, *end; + struct berval tmp; - tmp = ch_strdup( from_tbls->bv_val ); + ber_dupbv_x( &tmp, from_tbls, bsi->bsi_op->o_tmpmemctx ); - for ( start = tmp, end = strchr( start, ',' ); start; ) { + for ( start = tmp.bv_val, end = strchr( start, ',' ); start; ) { if ( end ) { end[0] = '\0'; } if ( strstr( bsi->bsi_from.bb_val.bv_val, start) == NULL ) { - backsql_strfcat( &bsi->bsi_from, "cs", ',', start ); + backsql_strfcat_x( &bsi->bsi_from, + bsi->bsi_op->o_tmpmemctx, + "cs", ',', start ); } if ( end ) { @@ -479,10 +632,12 @@ backsql_merge_from_tbls( backsql_srch_info *bsi, struct berval *from_tbls ) } } - ch_free( tmp ); + bsi->bsi_op->o_tmpfree( tmp.bv_val, bsi->bsi_op->o_tmpmemctx ); } else { - backsql_strfcat( &bsi->bsi_from, "b", from_tbls ); + backsql_strfcat_x( &bsi->bsi_from, + bsi->bsi_op->o_tmpmemctx, + "b", from_tbls ); } return LDAP_SUCCESS; @@ -519,11 +674,15 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) break; case LDAP_FILTER_NOT: - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "NOT (" /* ) */ ), "NOT (" /* ) */ ); rc = backsql_process_filter( bsi, f->f_not ); - backsql_strfcat( &bsi->bsi_flt_where, "c", /* ( */ ')' ); + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "c", /* ( */ ')' ); done = 1; break; @@ -542,7 +701,9 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) * ldap_entries AS attributeName WHERE attributeName.dn * like '%attributeName=value%'" */ - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "1=1" ), "1=1" ); bsi->bsi_status = LDAP_SUCCESS; rc = 1; @@ -602,12 +763,14 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) backsql_merge_from_tbls( bsi, &ldap_entry_objclasses ); - backsql_strfcat( &bsi->bsi_flt_where, "lbl", - (ber_len_t)STRLENOF( "2=2 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */ ), - "2=2 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */, + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "lbl", + (ber_len_t)STRLENOF( "(2=2 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ')) */ ), + "(2=2 OR (ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ')) */, &bsi->bsi_oc->bom_oc->soc_cname, - (ber_len_t)STRLENOF( /* (' */ "')" ), - /* (' */ "')" ); + (ber_len_t)STRLENOF( /* ((' */ "'))" ), + /* ((' */ "'))" ); bsi->bsi_status = LDAP_SUCCESS; rc = 1; goto done; @@ -617,7 +780,9 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) } case LDAP_FILTER_PRESENT: - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "3=3" ), "3=3" ); bsi->bsi_status = LDAP_SUCCESS; rc = 1; @@ -656,21 +821,27 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) } #ifdef BACKSQL_ARBITRARY_KEY - backsql_strfcat( &bsi->bsi_flt_where, "bcblbc", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "bcblbc", &bsi->bsi_oc->bom_keytbl, '.', &bsi->bsi_oc->bom_keycol, STRLENOF( " LIKE '" ), " LIKE '", &keyval, '\'' ); #else /* ! BACKSQL_ARBITRARY_KEY */ snprintf( keyvalbuf, sizeof( keyvalbuf ), "%lu", keyval ); - backsql_strfcat( &bsi->bsi_flt_where, "bcbcs", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "bcbcs", &bsi->bsi_oc->bom_keytbl, '.', &bsi->bsi_oc->bom_keycol, '=', keyvalbuf ); #endif /* ! BACKSQL_ARBITRARY_KEY */ break; case LDAP_FILTER_PRESENT: - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "4=4" ), "4=4" ); break; @@ -686,21 +857,24 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) #ifdef BACKSQL_SYNCPROV } else if ( ad == slap_schema.si_ad_entryCSN ) { /* - * TODO: introduce appropriate entryCSN filtering - * to support syncrepl as producer... + * support for syncrepl as producer... */ +#if 0 if ( !bsi->bsi_op->o_sync ) { /* unsupported at present... */ bsi->bsi_status = LDAP_OTHER; rc = -1; goto done; } +#endif bsi->bsi_flags |= ( BSQL_SF_FILTER_ENTRYCSN | BSQL_SF_RETURN_ENTRYUUID); /* if doing a syncrepl, try to return as much as possible, * and always match the filter */ - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "5=5" ), "5=5" ); /* save for later use in operational attributes */ @@ -734,7 +908,9 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) * selecting if there are descendants of the * candidate. */ - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "6=6" ), "6=6" ); if ( ad == slap_schema.si_ad_hasSubordinates ) { /* @@ -767,7 +943,9 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) if ( vat == NULL ) { /* search anyway; other parts of the filter * may succeeed */ - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "7=7" ), "7=7" ); bsi->bsi_status = LDAP_SUCCESS; rc = 1; @@ -777,7 +955,9 @@ backsql_process_filter( backsql_srch_info *bsi, Filter *f ) /* if required, open extra level of parens */ done = 0; if ( vat[0]->bam_next || vat[1] ) { - backsql_strfcat( &bsi->bsi_flt_where, "c", '(' ); + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "c", '(' ); done = 1; } @@ -790,7 +970,9 @@ next:; /* if more definitions of the same attr, apply */ if ( vat[i]->bam_next ) { - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", STRLENOF( " OR " ), " OR " ); vat[i] = vat[i]->bam_next; goto next; @@ -799,14 +981,18 @@ next:; /* if more descendants of the same attr, apply */ i++; if ( vat[i] ) { - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", STRLENOF( " OR " ), " OR " ); goto next; } /* if needed, close extra level of parens */ if ( done ) { - backsql_strfcat( &bsi->bsi_flt_where, "c", ')' ); + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "c", ')' ); } rc = 1; @@ -836,7 +1022,9 @@ backsql_process_filter_eq( backsql_srch_info *bsi, backsql_at_map_rec *at, if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { ber_len_t start; - backsql_strfcat( &bsi->bsi_flt_where, "cbl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "cbl", '(', /* ) */ &at->bam_sel_expr_u, (ber_len_t)STRLENOF( "='" ), @@ -844,7 +1032,9 @@ backsql_process_filter_eq( backsql_srch_info *bsi, backsql_at_map_rec *at, start = bsi->bsi_flt_where.bb_val.bv_len; - backsql_strfcat( &bsi->bsi_flt_where, "bl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "bl", filter_value, (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); @@ -852,7 +1042,9 @@ backsql_process_filter_eq( backsql_srch_info *bsi, backsql_at_map_rec *at, ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); } else { - backsql_strfcat( &bsi->bsi_flt_where, "cblbl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "cblbl", '(', /* ) */ &at->bam_sel_expr, (ber_len_t)STRLENOF( "='" ), "='", @@ -877,7 +1069,9 @@ backsql_process_filter_like( backsql_srch_info *bsi, backsql_at_map_rec *at, if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { ber_len_t start; - backsql_strfcat( &bsi->bsi_flt_where, "cbl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "cbl", '(', /* ) */ &at->bam_sel_expr_u, (ber_len_t)STRLENOF( " LIKE '%" ), @@ -885,7 +1079,9 @@ backsql_process_filter_like( backsql_srch_info *bsi, backsql_at_map_rec *at, start = bsi->bsi_flt_where.bb_val.bv_len; - backsql_strfcat( &bsi->bsi_flt_where, "bl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "bl", filter_value, (ber_len_t)STRLENOF( /* (' */ "%')" ), /* (' */ "%')" ); @@ -893,7 +1089,9 @@ backsql_process_filter_like( backsql_srch_info *bsi, backsql_at_map_rec *at, ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); } else { - backsql_strfcat( &bsi->bsi_flt_where, "cblbl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "cblbl", '(', /* ) */ &at->bam_sel_expr, (ber_len_t)STRLENOF( " LIKE '%" ), @@ -930,7 +1128,9 @@ backsql_process_filter_attr( backsql_srch_info *bsi, Filter *f, backsql_at_map_r && strstr( bsi->bsi_join_where.bb_val.bv_val, at->bam_join_where.bv_val ) == NULL ) { - backsql_strfcat( &bsi->bsi_join_where, "lb", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "lb", (ber_len_t)STRLENOF( " AND " ), " AND ", &at->bam_join_where ); } @@ -958,6 +1158,10 @@ equality_match:; casefold = 1; } + /* FIXME: directoryString filtering should use a similar + * approach to deal with non-prettified values like + * " A non prettified value ", by using a LIKE + * filter with all whitespaces collapsed to a single '%' */ if ( SLAP_MR_ASSOCIATED( matching_rule, bi->sql_telephoneNumberMatch ) ) { @@ -996,7 +1200,9 @@ equality_match:; if ( at->bam_ad == slap_schema.si_ad_objectClass || at->bam_ad == slap_schema.si_ad_structuralObjectClass ) { - backsql_strfcat( &bsi->bsi_flt_where, "lbl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "lbl", (ber_len_t)STRLENOF( "(ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */ ), "(ldap_entries.id=ldap_entry_objclasses.entry_id AND ldap_entry_objclasses.oc_name='" /* ') */, filter_value, @@ -1038,7 +1244,9 @@ equality_match:; if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { ber_len_t start; - backsql_strfcat( &bsi->bsi_flt_where, "cbbc", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "cbbc", '(', /* ) */ &at->bam_sel_expr_u, &ordering, @@ -1046,7 +1254,9 @@ equality_match:; start = bsi->bsi_flt_where.bb_val.bv_len; - backsql_strfcat( &bsi->bsi_flt_where, "bl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "bl", filter_value, (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); @@ -1054,7 +1264,9 @@ equality_match:; ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); } else { - backsql_strfcat( &bsi->bsi_flt_where, "cbbcbl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "cbbcbl", '(' /* ) */ , &at->bam_sel_expr, &ordering, @@ -1066,7 +1278,9 @@ equality_match:; break; case LDAP_FILTER_PRESENT: - backsql_strfcat( &bsi->bsi_flt_where, "lbl", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "lbl", (ber_len_t)STRLENOF( "NOT (" /* ) */), "NOT (", /* ) */ &at->bam_sel_expr, @@ -1093,7 +1307,9 @@ equality_match:; default: /* unhandled filter type; should not happen */ assert( 0 ); - backsql_strfcat( &bsi->bsi_flt_where, "l", + backsql_strfcat_x( &bsi->bsi_flt_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "8=8" ), "8=8" ); break; @@ -1108,10 +1324,10 @@ equality_match:; static int backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) { - backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private; - int rc; + backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private; + int rc; - assert( query ); + assert( query != NULL ); BER_BVZERO( query ); bsi->bsi_use_subtree_shortcut = 0; @@ -1127,7 +1343,9 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) BER_BVZERO( &bsi->bsi_flt_where.bb_val ); bsi->bsi_flt_where.bb_len = 0; - backsql_strfcat( &bsi->bsi_sel, "lbcbc", + backsql_strfcat_x( &bsi->bsi_sel, + bsi->bsi_op->o_tmpmemctx, + "lbcbc", (ber_len_t)STRLENOF( "SELECT DISTINCT ldap_entries.id," ), "SELECT DISTINCT ldap_entries.id,", &bsi->bsi_oc->bom_keytbl, @@ -1136,7 +1354,9 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) ',' ); if ( !BER_BVISNULL( &bi->sql_strcast_func ) ) { - backsql_strfcat( &bsi->bsi_sel, "blbl", + backsql_strfcat_x( &bsi->bsi_sel, + bsi->bsi_op->o_tmpmemctx, + "blbl", &bi->sql_strcast_func, (ber_len_t)STRLENOF( "('" /* ') */ ), "('" /* ') */ , @@ -1144,33 +1364,28 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) (ber_len_t)STRLENOF( /* (' */ "')" ), /* (' */ "')" ); } else { - backsql_strfcat( &bsi->bsi_sel, "cbc", + backsql_strfcat_x( &bsi->bsi_sel, + bsi->bsi_op->o_tmpmemctx, + "cbc", '\'', &bsi->bsi_oc->bom_oc->soc_cname, '\'' ); } -#ifdef BACKSQL_ALIASING_QUOTE - backsql_strfcat( &bsi->bsi_sel, "lclcl", - (ber_len_t)STRLENOF( " " BACKSQL_ALIASING ), - " " BACKSQL_ALIASING, - BACKSQL_ALIASING_QUOTE, - (ber_len_t)STRLENOF( "objectClass" ), - "objectClass", - BACKSQL_ALIASING_QUOTE, - (ber_len_t)STRLENOF( ",ldap_entries.dn " BACKSQL_ALIASING "dn" ), - ",ldap_entries.dn " BACKSQL_ALIASING "dn" ); -#else /* ! BACKSQL_ALIASING_QUOTE */ - backsql_strfcat( &bsi->bsi_sel, "l", - (ber_len_t)STRLENOF( " " BACKSQL_ALIASING "objectClass,ldap_entries.dn " BACKSQL_ALIASING "dn" ), - " " BACKSQL_ALIASING "objectClass,ldap_entries.dn " BACKSQL_ALIASING "dn" ); -#endif /* ! BACKSQL_ALIASING_QUOTE */ - - backsql_strfcat( &bsi->bsi_from, "lb", + + backsql_strfcat_x( &bsi->bsi_sel, + bsi->bsi_op->o_tmpmemctx, + "b", + &bi->sql_dn_oc_aliasing ); + backsql_strfcat_x( &bsi->bsi_from, + bsi->bsi_op->o_tmpmemctx, + "lb", (ber_len_t)STRLENOF( " FROM ldap_entries," ), " FROM ldap_entries,", &bsi->bsi_oc->bom_keytbl ); - backsql_strfcat( &bsi->bsi_join_where, "lbcbl", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "lbcbl", (ber_len_t)STRLENOF( " WHERE " ), " WHERE ", &bsi->bsi_oc->bom_keytbl, '.', @@ -1181,12 +1396,16 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) switch ( bsi->bsi_scope ) { case LDAP_SCOPE_BASE: if ( BACKSQL_CANUPPERCASE( bi ) ) { - backsql_strfcat( &bsi->bsi_join_where, "bl", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "bl", &bi->sql_upper_func, (ber_len_t)STRLENOF( "(ldap_entries.dn)=?" ), "(ldap_entries.dn)=?" ); } else { - backsql_strfcat( &bsi->bsi_join_where, "l", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "ldap_entries.dn=?" ), "ldap_entries.dn=?" ); } @@ -1194,32 +1413,36 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) case BACKSQL_SCOPE_BASE_LIKE: if ( BACKSQL_CANUPPERCASE( bi ) ) { - backsql_strfcat( &bsi->bsi_join_where, "bl", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "bl", &bi->sql_upper_func, (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE ?" ), "(ldap_entries.dn) LIKE ?" ); } else { - backsql_strfcat( &bsi->bsi_join_where, "l", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "ldap_entries.dn LIKE ?" ), "ldap_entries.dn LIKE ?" ); } break; case LDAP_SCOPE_ONELEVEL: - backsql_strfcat( &bsi->bsi_join_where, "l", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "ldap_entries.parent=?" ), "ldap_entries.parent=?" ); break; -#ifdef LDAP_SCOPE_SUBORDINATE case LDAP_SCOPE_SUBORDINATE: -#endif /* LDAP_SCOPE_SUBORDINATE */ case LDAP_SCOPE_SUBTREE: if ( BACKSQL_USE_SUBTREE_SHORTCUT( bi ) ) { int i; BackendDB *bd = bsi->bsi_op->o_bd; - assert( bd->be_nsuffix ); + assert( bd->be_nsuffix != NULL ); for ( i = 0; !BER_BVISNULL( &bd->be_nsuffix[ i ] ); i++ ) { @@ -1237,20 +1460,29 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) if ( bsi->bsi_use_subtree_shortcut ) { /* Skip the base DN filter, as every entry will match it */ - backsql_strfcat( &bsi->bsi_join_where, "l", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "9=9"), "9=9"); } else if ( !BER_BVISNULL( &bi->sql_subtree_cond ) ) { - backsql_strfcat( &bsi->bsi_join_where, "b", &bi->sql_subtree_cond ); + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "b", + &bi->sql_subtree_cond ); } else if ( BACKSQL_CANUPPERCASE( bi ) ) { - backsql_strfcat( &bsi->bsi_join_where, "bl", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "bl", &bi->sql_upper_func, (ber_len_t)STRLENOF( "(ldap_entries.dn) LIKE ?" ), "(ldap_entries.dn) LIKE ?" ); } else { - backsql_strfcat( &bsi->bsi_join_where, "l", + backsql_strfcat_x( &bsi->bsi_join_where, + bsi->bsi_op->o_tmpmemctx, + "l", (ber_len_t)STRLENOF( "ldap_entries.dn LIKE ?" ), "ldap_entries.dn LIKE ?" ); } @@ -1265,7 +1497,9 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) if ( rc > 0 ) { struct berbuf bb = BB_NULL; - backsql_strfcat( &bb, "bbblb", + backsql_strfcat_x( &bb, + bsi->bsi_op->o_tmpmemctx, + "bbblb", &bsi->bsi_sel.bb_val, &bsi->bsi_from.bb_val, &bsi->bsi_join_where.bb_val, @@ -1283,16 +1517,16 @@ backsql_srch_query( backsql_srch_info *bsi, struct berval *query ) BER_BVZERO( query ); } - free( bsi->bsi_sel.bb_val.bv_val ); + 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; - free( bsi->bsi_from.bb_val.bv_val ); + 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; - free( bsi->bsi_join_where.bb_val.bv_val ); + 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; - free( bsi->bsi_flt_where.bb_val.bv_val ); + 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; @@ -1307,6 +1541,7 @@ backsql_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; @@ -1331,6 +1566,12 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) 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 ); @@ -1379,7 +1620,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) query.bv_val, 0, 0 ); rc = backsql_Prepare( bsi->bsi_dbh, &sth, query.bv_val, 0 ); - free( query.bv_val ); + 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(): " @@ -1436,9 +1677,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) } break; -#ifdef LDAP_SCOPE_SUBORDINATE case LDAP_SCOPE_SUBORDINATE: -#endif /* LDAP_SCOPE_SUBORDINATE */ case LDAP_SCOPE_SUBTREE: { /* if short-cutting the search base, @@ -1477,11 +1716,9 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) tmp_base_ndn[ i ] = bsi->bsi_base_ndn->bv_val[ j ]; } -#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'; @@ -1491,11 +1728,9 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) 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 ); @@ -1507,13 +1742,10 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) ldap_pvt_str2upper( tmp_base_ndn ); } -#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 */ - { + } else { Debug( LDAP_DEBUG_TRACE, "(sub)dn: \"%s\"\n", tmp_base_ndn, 0, 0 ); } @@ -1563,7 +1795,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) return BACKSQL_AVL_CONTINUE; } - backsql_BindRowAsStrings( sth, &row ); + 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; @@ -1576,7 +1808,7 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) continue; } - ret = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL ); + ret = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx ); if ( dn.bv_val != row.cols[ 3 ] ) { free( dn.bv_val ); } @@ -1586,19 +1818,23 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) } if ( bi->sql_baseObject && dn_match( &ndn, &bi->sql_baseObject->e_nname ) ) { - free( pdn.bv_val ); - free( ndn.bv_val ); - continue; + goto cleanup; } - c_id = (backsql_entryID *)ch_calloc( 1, - sizeof( backsql_entryID ) ); + c_id = (backsql_entryID *)op->o_tmpcalloc( 1, + sizeof( backsql_entryID ), op->o_tmpmemctx ); #ifdef BACKSQL_ARBITRARY_KEY - ber_str2bv( row.cols[ 0 ], 0, 1, &c_id->eid_id ); - ber_str2bv( row.cols[ 1 ], 0, 1, &c_id->eid_keyval ); + 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 */ - c_id->eid_id = strtol( row.cols[ 0 ], NULL, 0 ); - c_id->eid_keyval = strtol( row.cols[ 1 ], NULL, 0 ); + 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; @@ -1626,8 +1862,20 @@ backsql_oc_get_candidates( void *v_oc, void *v_bsi ) 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( &row ); + backsql_FreeRow_x( &row, bsi->bsi_op->o_tmpmemctx ); SQLFreeStmt( sth, SQL_DROP ); Debug( LDAP_DEBUG_TRACE, "<==backsql_oc_get_candidates(): %d\n", @@ -1642,20 +1890,18 @@ backsql_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 }; - int manageDSAit; + Entry user_entry = { 0 }, + base_entry = { 0 }; + int manageDSAit = get_manageDSAit( op ); time_t stoptime = 0; - backsql_srch_info bsi; + backsql_srch_info bsi = { 0 }; backsql_entryID *eid = NULL; - struct berval nbase = BER_BVNULL, - realndn = BER_BVNULL; - - manageDSAit = get_manageDSAit( op ); + 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_filterstr.bv_val : "(no filter)", + op->ors_filterstr.bv_val, op->ors_scope ); Debug( LDAP_DEBUG_TRACE, " deref=%d, attrsonly=%d, " "attributes to load: %s\n", @@ -1691,28 +1937,96 @@ backsql_search( Operation *op, SlapReply *rs ) /* compute it anyway; root does not use it */ stoptime = op->o_time + op->ors_tlimit; - realndn = op->o_req_ndn; - if ( backsql_api_dn2odbc( op, rs, &realndn ) ) { - Debug( LDAP_DEBUG_TRACE, " backsql_search(\"%s\"): " - "backsql_api_dn2odbc(\"%s\") failed\n", - op->o_req_ndn.bv_val, realndn.bv_val, 0 ); - rs->sr_err = LDAP_OTHER; - rs->sr_text = "SQL-backend error"; - send_ldap_result( op, rs ); - goto done; - } - /* init search */ - rs->sr_err = backsql_init_search( &bsi, &realndn, + bsi.bsi_e = &base_entry; + rs->sr_err = backsql_init_search( &bsi, &op->o_req_ndn, op->ors_scope, - op->ors_slimit, op->ors_tlimit, stoptime, op->ors_filter, dbh, op, rs, op->ors_attrs, - BACKSQL_ISF_GET_ID ); - if ( rs->sr_err != LDAP_SUCCESS ) { + ( 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: + 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; + } + 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; } + /* 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; + } + } + + bsi.bsi_e = NULL; bsi.bsi_n_candidates = ( op->ors_limit == NULL /* isroot == TRUE */ ? -2 : @@ -1750,6 +2064,13 @@ backsql_search( Operation *op, SlapReply *rs ) */ avl_apply( bi->sql_oc_by_oc, backsql_oc_get_candidates, &bsi, BACKSQL_AVL_STOP, AVL_INORDER ); + + /* check for abandon */ + if ( op->o_abandon ) { + eid = bsi.bsi_id_list; + rs->sr_err = SLAPD_ABANDON; + goto send_results; + } } if ( op->ors_limit != NULL /* isroot == FALSE */ @@ -1768,7 +2089,8 @@ backsql_search( Operation *op, SlapReply *rs ) */ for ( eid = bsi.bsi_id_list; eid != NULL; - eid = backsql_free_entryID( eid, eid == &bsi.bsi_base_id ? 0 : 1 ) ) + eid = backsql_free_entryID( op, + eid, eid == &bsi.bsi_base_id ? 0 : 1 ) ) { int rc; Attribute *a_hasSubordinate = NULL, @@ -1779,7 +2101,8 @@ backsql_search( Operation *op, SlapReply *rs ) /* check for abandon */ if ( op->o_abandon ) { - break; + rs->sr_err = SLAPD_ABANDON; + goto send_results; } /* check time limit */ @@ -1789,10 +2112,7 @@ backsql_search( Operation *op, SlapReply *rs ) rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; rs->sr_ctrls = NULL; rs->sr_ref = rs->sr_v2ref; - rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS - : LDAP_REFERRAL; - send_ldap_result( op, rs ); - goto end_of_search; + goto send_results; } #ifdef BACKSQL_ARBITRARY_KEY @@ -1826,27 +2146,29 @@ backsql_search( Operation *op, SlapReply *rs ) /* fall thru */ } -#ifdef LDAP_SCOPE_SUBORDINATE case LDAP_SCOPE_SUBORDINATE: /* discard the baseObject entry */ if ( dn_match( &eid->eid_ndn, &op->o_req_ndn ) ) { goto next_entry2; } - /* FALLTHRU */ -#endif /* LDAP_SCOPE_SUBORDINATE */ - + /* FALLTHRU */ case LDAP_SCOPE_SUBTREE: /* FIXME: this should never fail... */ if ( !dnIsSuffix( &eid->eid_ndn, &op->o_req_ndn ) ) { + assert( 0 ); goto next_entry2; } break; } - /* don't recollect baseObject ... */ if ( BACKSQL_IS_BASEOBJECT_ID( &eid->eid_id ) ) { + /* don't recollect baseObject... */ e = bi->sql_baseObject; + } else if ( eid == &bsi.bsi_base_id ) { + /* don't recollect searchBase object... */ + e = &base_entry; + } else { bsi.bsi_e = &user_entry; rc = backsql_id2entry( &bsi, eid ); @@ -1856,7 +2178,6 @@ backsql_search( Operation *op, SlapReply *rs ) "- skipping\n", rc, 0, 0 ); continue; } - e = &user_entry; } @@ -1873,21 +2194,26 @@ backsql_search( Operation *op, SlapReply *rs ) Entry user_entry2 = { 0 }; /* retry with the full entry... */ - (void)backsql_init_search( &bsi2, + bsi2.bsi_e = &user_entry2; + rc = backsql_init_search( &bsi2, &e->e_nname, LDAP_SCOPE_BASE, - SLAP_NO_LIMIT, SLAP_NO_LIMIT, (time_t)(-1), NULL, - dbh, op, rs, NULL, 0 ); - bsi2.bsi_e = &user_entry2; - rc = backsql_id2entry( &bsi2, eid ); + dbh, op, rs, NULL, + BACKSQL_ISF_GET_ENTRY ); if ( rc == LDAP_SUCCESS ) { if ( is_entry_referral( &user_entry2 ) ) { refs = get_entry_referrals( op, &user_entry2 ); - } /* else: FIXME: inconsistency! */ - entry_clean( &user_entry2 ); + } else { + rs->sr_err = LDAP_OTHER; + } + backsql_entry_clean( op, &user_entry2 ); + } + if ( bsi2.bsi_attrs != NULL ) { + op->o_tmpfree( bsi2.bsi_attrs, + op->o_tmpmemctx ); } } @@ -1899,12 +2225,14 @@ backsql_search( Operation *op, SlapReply *rs ) ber_bvarray_free( refs ); } - if ( !rs->sr_ref ) { - rs->sr_text = "bad_referral object"; + if ( rs->sr_ref ) { + rs->sr_err = LDAP_REFERRAL; + + } else { + rs->sr_text = "bad referral object"; } rs->sr_entry = e; - rs->sr_err = LDAP_REFERRAL; rs->sr_matched = user_entry.e_name.bv_val; send_search_reference( op, rs ); @@ -1922,7 +2250,7 @@ backsql_search( Operation *op, SlapReply *rs ) * filter_has_subordinates() */ if ( bsi.bsi_flags & BSQL_SF_FILTER_HASSUBORDINATE ) { - rc = backsql_has_children( bi, dbh, &e->e_nname ); + rc = backsql_has_children( op, dbh, &e->e_nname ); switch ( rc ) { case LDAP_COMPARE_TRUE: @@ -1981,47 +2309,37 @@ backsql_search( Operation *op, SlapReply *rs ) rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_entry = e; - if ( e == &user_entry ) { - rs->sr_flags = REP_ENTRY_MODIFIABLE; - } - sres = send_search_entry( op, rs ); + rs->sr_flags = ( e == &user_entry ) ? REP_ENTRY_MODIFIABLE : 0; + /* FIXME: need the whole entry (ITS#3480) */ + rs->sr_err = send_search_entry( op, rs ); rs->sr_entry = NULL; rs->sr_attrs = NULL; rs->sr_operational_attrs = NULL; - switch ( sres ) { - case 0: - break; - - default: + switch ( rs->sr_err ) { + case LDAP_UNAVAILABLE: /* * FIXME: send_search_entry failed; * better stop */ - case -1: Debug( LDAP_DEBUG_TRACE, "backsql_search(): " "connection lost\n", 0, 0, 0 ); goto end_of_search; + + case LDAP_SIZELIMIT_EXCEEDED: + goto send_results; } } next_entry:; - entry_clean( &user_entry ); + if ( e == &user_entry ) { + backsql_entry_clean( op, &user_entry ); + } next_entry2:; - if ( op->ors_slimit != SLAP_NO_LIMIT - && rs->sr_nentries >= op->ors_slimit ) - { - rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; - send_ldap_result( op, rs ); - goto end_of_search; - } } end_of_search:; - /* in case we got here accidentally */ - entry_clean( &user_entry ); - if ( rs->sr_nentries > 0 ) { rs->sr_ref = rs->sr_v2ref; rs->sr_err = (rs->sr_v2ref == NULL) ? LDAP_SUCCESS @@ -2030,7 +2348,22 @@ end_of_search:; } else { rs->sr_err = bsi.bsi_status; } - send_ldap_result( op, rs ); + +send_results:; + if ( rs->sr_err != SLAPD_ABANDON ) { + send_ldap_result( op, rs ); + } + + /* cleanup in case of abandon */ + for ( ; eid != NULL; + eid = backsql_free_entryID( op, + eid, eid == &bsi.bsi_base_id ? 0 : 1 ) ) + ; + + backsql_entry_clean( op, &base_entry ); + + /* in case we got here accidentally */ + backsql_entry_clean( op, &user_entry ); if ( rs->sr_v2ref ) { ber_bvarray_free( rs->sr_v2ref ); @@ -2059,16 +2392,10 @@ end_of_search:; #endif /* BACKSQL_SYNCPROV */ done:; - if ( !BER_BVISNULL( &realndn ) && realndn.bv_val != op->o_req_ndn.bv_val ) { - ch_free( realndn.bv_val ); - } - - if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { - (void)backsql_free_entryID( &bsi.bsi_base_id, 0 ); - } + (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); - if ( bsi.bsi_attrs ) { - ch_free( bsi.bsi_attrs ); + if ( bsi.bsi_attrs != NULL ) { + op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); } if ( !BER_BVISNULL( &nbase ) @@ -2084,7 +2411,8 @@ done:; } Debug( LDAP_DEBUG_TRACE, "<==backsql_search()\n", 0, 0, 0 ); - return 0; + + return rs->sr_err; } /* return LDAP_SUCCESS IFF we can retrieve the specified entry. @@ -2098,12 +2426,14 @@ backsql_entry_get( int rw, Entry **ent ) { - backsql_srch_info bsi; + backsql_srch_info bsi = { 0 }; SQLHDBC dbh = SQL_NULL_HDBC; int rc; SlapReply rs = { 0 }; AttributeName anlist[ 2 ]; + *ent = NULL; + rc = backsql_get_db_conn( op, &dbh ); if ( !dbh ) { return LDAP_OTHER; @@ -2115,22 +2445,16 @@ backsql_entry_get( BER_BVZERO( &anlist[ 1 ].an_name ); } + bsi.bsi_e = ch_malloc( sizeof( Entry ) ); rc = backsql_init_search( &bsi, ndn, LDAP_SCOPE_BASE, - SLAP_NO_LIMIT, SLAP_NO_LIMIT, (time_t)(-1), NULL, dbh, op, &rs, at ? anlist : NULL, - BACKSQL_ISF_GET_ID ); - if ( rc != LDAP_SUCCESS ) { - return rc; - } - - bsi.bsi_e = ch_malloc( sizeof( Entry ) ); - rc = backsql_id2entry( &bsi, &bsi.bsi_base_id ); + BACKSQL_ISF_GET_ENTRY ); if ( !BER_BVISNULL( &bsi.bsi_base_id.eid_ndn ) ) { - (void)backsql_free_entryID( &bsi.bsi_base_id, 0 ); + (void)backsql_free_entryID( op, &bsi.bsi_base_id, 0 ); } if ( rc == LDAP_SUCCESS ) { @@ -2167,6 +2491,10 @@ backsql_entry_get( } return_results:; + if ( bsi.bsi_attrs != NULL ) { + op->o_tmpfree( bsi.bsi_attrs, op->o_tmpmemctx ); + } + if ( rc != LDAP_SUCCESS ) { if ( bsi.bsi_e ) { entry_free( bsi.bsi_e ); @@ -2176,3 +2504,39 @@ return_results:; return rc; } +void +backsql_entry_clean( + Operation *op, + Entry *e ) +{ + void *ctx; + + ctx = ldap_pvt_thread_pool_context(); + + if ( ctx == NULL || ctx != op->o_tmpmemctx ) { + if ( !BER_BVISNULL( &e->e_name ) ) { + op->o_tmpfree( e->e_name.bv_val, op->o_tmpmemctx ); + BER_BVZERO( &e->e_name ); + } + + if ( !BER_BVISNULL( &e->e_nname ) ) { + op->o_tmpfree( e->e_nname.bv_val, op->o_tmpmemctx ); + BER_BVZERO( &e->e_nname ); + } + } + + entry_clean( e ); +} + +int +backsql_entry_release( + Operation *op, + Entry *e, + int rw ) +{ + backsql_entry_clean( op, e ); + + ch_free( e ); + + return 0; +}