From 87df6c19915042430540931d199a39105544a134 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Wed, 23 Mar 2022 12:43:31 +0000 Subject: [PATCH] ITS#9815 slapd-sql: escape filter values --- servers/slapd/back-sql/search.c | 123 +++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 18 deletions(-) --- a/servers/slapd/back-sql/search.c +++ b/servers/slapd/back-sql/search.c @@ -63,6 +63,38 @@ ID *lastid ); #endif /* ! BACKSQL_ARBITRARY_KEY */ +/* Look for chars that need to be escaped, return count of them. + * If out is non-NULL, copy escape'd val to it. + */ +static int +backsql_val_escape( Operation *op, struct berval *in, struct berval *out ) +{ + char *ptr, *end; + int q = 0; + + ptr = in->bv_val; + end = ptr + in->bv_len; + while (ptr < end) { + if ( *ptr == '\'' ) + q++; + ptr++; + } + if ( q && out ) { + char *dst; + out->bv_len = in->bv_len + q; + out->bv_val = op->o_tmpalloc( out->bv_len + 1, op->o_tmpmemctx ); + ptr = in->bv_val; + dst = out->bv_val; + while (ptr < end ) { + if ( *ptr == '\'' ) + *dst++ = '\''; + *dst++ = *ptr++; + } + *dst = '\0'; + } + return q; +} + static int backsql_attrlist_add( backsql_srch_info *bsi, AttributeDescription *ad ) { @@ -429,6 +461,8 @@ backsql_info *bi = (backsql_info *)bsi->bsi_op->o_bd->be_private; int i; int casefold = 0; + int escaped = 0; + struct berval escval, *fvalue; if ( !f ) { return 0; @@ -462,50 +496,68 @@ BER_BVZERO( &bv ); if ( f->f_sub_initial.bv_val ) { - bv.bv_len += f->f_sub_initial.bv_len; + bv.bv_len += f->f_sub_initial.bv_len + backsql_val_escape( NULL, &f->f_sub_initial, NULL ); } if ( f->f_sub_any != NULL ) { for ( a = 0; f->f_sub_any[ a ].bv_val != NULL; a++ ) { - bv.bv_len += f->f_sub_any[ a ].bv_len; + bv.bv_len += f->f_sub_any[ a ].bv_len + backsql_val_escape( NULL, &f->f_sub_any[ a ], NULL ); } } if ( f->f_sub_final.bv_val ) { - bv.bv_len += f->f_sub_final.bv_len; + bv.bv_len += f->f_sub_final.bv_len + backsql_val_escape( NULL, &f->f_sub_final, NULL ); } bv.bv_len = 2 * bv.bv_len - 1; bv.bv_val = ch_malloc( bv.bv_len + 1 ); s = 0; if ( !BER_BVISNULL( &f->f_sub_initial ) ) { - bv.bv_val[ s ] = f->f_sub_initial.bv_val[ 0 ]; - for ( i = 1; i < f->f_sub_initial.bv_len; i++ ) { + fvalue = &f->f_sub_initial; + escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval ); + if ( escaped ) + fvalue = &escval; + bv.bv_val[ s ] = fvalue->bv_val[ 0 ]; + for ( i = 1; i < fvalue->bv_len; i++ ) { bv.bv_val[ s + 2 * i - 1 ] = '%'; - bv.bv_val[ s + 2 * i ] = f->f_sub_initial.bv_val[ i ]; + bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ]; } bv.bv_val[ s + 2 * i - 1 ] = '%'; s += 2 * i; + if ( escaped ) + bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx ); } if ( f->f_sub_any != NULL ) { for ( a = 0; !BER_BVISNULL( &f->f_sub_any[ a ] ); a++ ) { - bv.bv_val[ s ] = f->f_sub_any[ a ].bv_val[ 0 ]; - for ( i = 1; i < f->f_sub_any[ a ].bv_len; i++ ) { + fvalue = &f->f_sub_any[ a ]; + escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval ); + if ( escaped ) + fvalue = &escval; + bv.bv_val[ s ] = fvalue->bv_val[ 0 ]; + for ( i = 1; i < fvalue->bv_len; i++ ) { bv.bv_val[ s + 2 * i - 1 ] = '%'; - bv.bv_val[ s + 2 * i ] = f->f_sub_any[ a ].bv_val[ i ]; + bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ]; } bv.bv_val[ s + 2 * i - 1 ] = '%'; s += 2 * i; + if ( escaped ) + bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx ); } } if ( !BER_BVISNULL( &f->f_sub_final ) ) { - bv.bv_val[ s ] = f->f_sub_final.bv_val[ 0 ]; - for ( i = 1; i < f->f_sub_final.bv_len; i++ ) { + fvalue = &f->f_sub_final; + escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval ); + if ( escaped ) + fvalue = &escval; + bv.bv_val[ s ] = fvalue->bv_val[ 0 ]; + for ( i = 1; i < fvalue->bv_len; i++ ) { bv.bv_val[ s + 2 * i - 1 ] = '%'; - bv.bv_val[ s + 2 * i ] = f->f_sub_final.bv_val[ i ]; + bv.bv_val[ s + 2 * i ] = fvalue->bv_val[ i ]; } - bv.bv_val[ s + 2 * i - 1 ] = '%'; + bv.bv_val[ s + 2 * i - 1 ] = '%'; s += 2 * i; + if ( escaped ) + bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx ); } bv.bv_val[ s - 1 ] = '\0'; @@ -561,11 +613,17 @@ f->f_sub_initial.bv_val, 0 ); #endif /* BACKSQL_TRACE */ + fvalue = &f->f_sub_initial; + escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval ); + if ( escaped ) + fvalue = &escval; start = bsi->bsi_flt_where.bb_val.bv_len; backsql_strfcat_x( &bsi->bsi_flt_where, bsi->bsi_op->o_tmpmemctx, "b", - &f->f_sub_initial ); + fvalue ); + if ( escaped ) + bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx ); if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); } @@ -586,12 +644,18 @@ i, f->f_sub_any[ i ].bv_val ); #endif /* BACKSQL_TRACE */ + fvalue = &f->f_sub_any[ i ]; + escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval ); + if ( escaped ) + fvalue = &escval; start = bsi->bsi_flt_where.bb_val.bv_len; backsql_strfcat_x( &bsi->bsi_flt_where, bsi->bsi_op->o_tmpmemctx, "bc", - &f->f_sub_any[ i ], + fvalue, '%' ); + if ( escaped ) + bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx ); if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { /* * Note: toupper('%') = '%' @@ -611,11 +675,17 @@ f->f_sub_final.bv_val, 0 ); #endif /* BACKSQL_TRACE */ + fvalue = &f->f_sub_final; + escaped = backsql_val_escape( bsi->bsi_op, fvalue, &escval ); + if ( escaped ) + fvalue = &escval; start = bsi->bsi_flt_where.bb_val.bv_len; backsql_strfcat_x( &bsi->bsi_flt_where, bsi->bsi_op->o_tmpmemctx, "b", - &f->f_sub_final ); + fvalue ); + if ( escaped ) + bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx ); if ( casefold && BACKSQL_AT_CANUPPERCASE( at ) ) { ldap_pvt_str2upper( &bsi->bsi_flt_where.bb_val.bv_val[ start ] ); } @@ -1183,6 +1253,8 @@ struct berval *filter_value = NULL; MatchingRule *matching_rule = NULL; struct berval ordering = BER_BVC("<="); + struct berval escval; + int escaped = 0; Debug( LDAP_DEBUG_TRACE, "==>backsql_process_filter_attr(%s)\n", at->bam_ad->ad_cname.bv_val, 0, 0 ); @@ -1237,6 +1309,10 @@ casefold = 1; } + escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval ); + if ( escaped ) + filter_value = &escval; + /* FIXME: directoryString filtering should use a similar * approach to deal with non-prettified values like * " A non prettified value ", by using a LIKE @@ -1317,6 +1393,10 @@ casefold = 1; } + escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval ); + if ( escaped ) + filter_value = &escval; + /* * FIXME: should we uppercase the operands? */ @@ -1350,7 +1430,7 @@ &at->bam_sel_expr, &ordering, '\'', - &f->f_av_value, + filter_value, (ber_len_t)STRLENOF( /* (' */ "')" ), /* ( */ "')" ); } @@ -1374,13 +1454,17 @@ case LDAP_FILTER_APPROX: /* we do our best */ + filter_value = &f->f_av_value; + escaped = backsql_val_escape( bsi->bsi_op, filter_value, &escval ); + if ( escaped ) + filter_value = &escval; /* * maybe we should check type of at->sel_expr here somehow, * to know whether upper_func is applicable, but for now * upper_func stuff is made for Oracle, where UPPER is * safely applicable to NUMBER etc. */ - (void)backsql_process_filter_like( bsi, at, 1, &f->f_av_value ); + (void)backsql_process_filter_like( bsi, at, 1, filter_value ); break; default: @@ -1394,6 +1478,9 @@ } + if ( escaped ) + bsi->bsi_op->o_tmpfree( escval.bv_val, bsi->bsi_op->o_tmpmemctx ); + Debug( LDAP_DEBUG_TRACE, "<==backsql_process_filter_attr(%s)\n", at->bam_ad->ad_cname.bv_val, 0, 0 );