openldap/servers/slapd/matchedValues.c
Kurt Zeilenga 8c152396b9 Matched Values implementation (ITS#1776) based upon submission
form Mikhail Sahalaev <M.Sahalayev@pgr.salford.ac.uk>.
Further work needed:
	add testxxx-matchedvalues
	rework ldapsearch(1) portion of patch to generalize use of options
---
Copyright 2001, Mikhail Sahalaev, All rights reserved.
This software is not subject to any license of University Of
Salford.

Redistribution and use in source and binary forms are permitted
without restriction or fee of any kind as long as this notice
is preserved.
2002-05-02 18:56:56 +00:00

423 lines
8 KiB
C

/* $OpenLDAP$ */
/*
* Copyright 1999-2002 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted only
* as authorized by the OpenLDAP Public License. A copy of this
* license is available at http://www.OpenLDAP.org/license.html or
* in file LICENSE in the top-level directory of the distribution.
*/
#include "portable.h"
#include <stdio.h>
#include <ac/string.h>
#include <ac/socket.h>
#include "slap.h"
#include "../../libraries/liblber/lber-int.h"
static int test_mra_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
MatchingRuleAssertion *mra,
char ***e_flags
);
static int
test_substrings_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
ValuesReturnFilter *f,
char ***e_flags
);
static int
test_presence_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
AttributeDescription *desc,
char ***e_flags
);
static int
test_ava_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
AttributeAssertion *ava,
int type,
char ***e_flags
);
int
filter_matched_values(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
char ***e_flags
)
{
ValuesReturnFilter *f;
Attribute *a;
struct berval *bv;
char filter_found;
int i, j;
int rc = LDAP_SUCCESS;
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
"filter_matched_values: begin\n" ));
#else
Debug( LDAP_DEBUG_FILTER, "=> filter_matched_values\n", 0, 0, 0 );
#endif
for ( f = op->vrFilter; f != NULL; f = f->f_next ) {
switch ( f->f_choice ) {
case SLAPD_FILTER_COMPUTED:
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
"test_vrFilter: COMPUTED %s (%d)\n",
f->f_result == LDAP_COMPARE_FALSE ? "false" :
f->f_result == LDAP_COMPARE_TRUE ? "true" :
f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" :
"error",
f->f_result ));
#else
Debug( LDAP_DEBUG_FILTER, " COMPUTED %s (%d)\n",
f->f_result == LDAP_COMPARE_FALSE ? "false" :
f->f_result == LDAP_COMPARE_TRUE ? "true" :
f->f_result == SLAPD_COMPARE_UNDEFINED ? "undefined" : "error",
f->f_result, 0 );
#endif
/*This type of filter does not affect the result */
rc = LDAP_SUCCESS;
break;
case LDAP_FILTER_EQUALITY:
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
"test_vrFilter: EQUALITY\n" ));
#else
Debug( LDAP_DEBUG_FILTER, " EQUALITY\n", 0, 0, 0 );
#endif
rc = test_ava_vrFilter( be, conn, op, e, f->f_ava,
LDAP_FILTER_EQUALITY, e_flags );
if( rc == -1 ) {
return rc;
}
break;
case LDAP_FILTER_SUBSTRINGS:
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
"test_vrFilter SUBSTRINGS\n" ));
#else
Debug( LDAP_DEBUG_FILTER, " SUBSTRINGS\n", 0, 0, 0 );
#endif
rc = test_substrings_vrFilter( be, conn, op, e,
f, e_flags );
if( rc == -1 ) {
return rc;
}
break;
case LDAP_FILTER_PRESENT:
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
"test_vrFilter: PRESENT\n" ));
#else
Debug( LDAP_DEBUG_FILTER, " PRESENT\n", 0, 0, 0 );
#endif
rc = test_presence_vrFilter( be, conn, op, e,
f->f_desc, e_flags );
if( rc == -1 ) {
return rc;
}
break;
case LDAP_FILTER_GE:
rc = test_ava_vrFilter( be, conn, op, e, f->f_ava,
LDAP_FILTER_GE, e_flags );
if( rc == -1 ) {
return rc;
}
break;
case LDAP_FILTER_LE:
rc = test_ava_vrFilter( be, conn, op, e, f->f_ava,
LDAP_FILTER_LE, e_flags );
if( rc == -1 ) {
return rc;
}
break;
case LDAP_FILTER_EXT:
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_DETAIL1,
"test_vrFilter: EXT\n" ));
#else
Debug( LDAP_DEBUG_FILTER, " EXT\n", 0, 0, 0 );
#endif
rc = test_mra_vrFilter( be, conn, op, e,
f->f_mra, e_flags );
if( rc == -1 ) {
return rc;
}
break;
default:
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_INFO,
"test_vrFilter: unknown filter type %lu\n",
f->f_choice ));
#else
Debug( LDAP_DEBUG_ANY, " unknown filter type %lu\n",
f->f_choice, 0, 0 );
#endif
rc = LDAP_PROTOCOL_ERROR;
}
}
#ifdef NEW_LOGGING
LDAP_LOG(( "filter", LDAP_LEVEL_ENTRY,
"filter_matched_values: return=%d\n", rc ));
#else
Debug( LDAP_DEBUG_FILTER, "<= filter_matched_values %d\n", rc, 0, 0 );
#endif
return( rc );
}
static int
test_ava_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
AttributeAssertion *ava,
int type,
char ***e_flags
)
{
int rc;
int i, j;
Attribute *a;
if ( !access_allowed( be, conn, op, e,
ava->aa_desc, &ava->aa_value, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
MatchingRule *mr;
struct berval *bv;
if ( !is_ad_subtype( a->a_desc, ava->aa_desc ) ) {
continue;
}
switch ( type ) {
case LDAP_FILTER_APPROX:
mr = a->a_desc->ad_type->sat_approx;
if( mr != NULL ) break;
/* use EQUALITY matching rule if no APPROX rule */
case LDAP_FILTER_EQUALITY:
mr = a->a_desc->ad_type->sat_equality;
break;
case LDAP_FILTER_GE:
case LDAP_FILTER_LE:
mr = a->a_desc->ad_type->sat_ordering;
break;
default:
mr = NULL;
}
if( mr == NULL ) {
continue;
}
for ( bv = a->a_vals, j=0; bv->bv_val != NULL; bv++, j++ ) {
int ret;
int rc;
const char *text;
rc = value_match( &ret, a->a_desc, mr,
SLAP_MR_ASSERTION_SYNTAX_MATCH, bv, &ava->aa_value, &text );
if( rc != LDAP_SUCCESS ) {
return rc;
}
switch ( type ) {
case LDAP_FILTER_EQUALITY:
case LDAP_FILTER_APPROX:
if ( ret == 0 ) {
(*e_flags)[i][j] = 1;
}
break;
case LDAP_FILTER_GE:
if ( ret >= 0 ) {
(*e_flags)[i][j] = 1;
}
break;
case LDAP_FILTER_LE:
if ( ret <= 0 ) {
(*e_flags)[i][j] = 1;
}
break;
}
}
}
return( LDAP_SUCCESS );
}
static int
test_presence_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
AttributeDescription *desc,
char ***e_flags
)
{
int i, j;
Attribute *a;
if ( !access_allowed( be, conn, op, e, desc, NULL, ACL_SEARCH, NULL ) ) {
return LDAP_INSUFFICIENT_ACCESS;
}
for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
struct berval *bv;
if ( !is_ad_subtype( a->a_desc, desc ) ) {
continue;
}
for ( bv = a->a_vals, j=0; bv->bv_val != NULL; bv++, j++ );
memset( (*e_flags)[i], 1, j);
}
return( LDAP_SUCCESS );
}
static int
test_substrings_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
ValuesReturnFilter *f,
char ***e_flags
)
{
int i, j;
Attribute *a;
if ( !access_allowed( be, conn, op, e,
f->f_sub_desc, NULL, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
MatchingRule *mr = a->a_desc->ad_type->sat_substr;
struct berval *bv;
if ( !is_ad_subtype( a->a_desc, f->f_sub_desc ) ) {
continue;
}
if( mr == NULL ) {
continue;
}
for ( bv = a->a_vals, j = 0; bv->bv_val != NULL; bv++, j++ ) {
int ret;
int rc;
const char *text;
rc = value_match( &ret, a->a_desc, mr,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
bv, f->f_sub, &text );
if( rc != LDAP_SUCCESS ) {
return rc;
}
if ( ret == 0 ) {
(*e_flags)[i][j] = 1;
}
}
}
return LDAP_SUCCESS;
}
static int test_mra_vrFilter(
Backend *be,
Connection *conn,
Operation *op,
Entry *e,
MatchingRuleAssertion *mra,
char ***e_flags
)
{
int i, j;
Attribute *a;
if( !access_allowed( be, conn, op, e,
mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) )
{
return LDAP_INSUFFICIENT_ACCESS;
}
for (a = e->e_attrs, i=0; a != NULL; a = a->a_next, i++ ) {
struct berval *bv;
if ( !is_ad_subtype( a->a_desc, mra->ma_desc ) ) {
return( LDAP_SUCCESS );
}
for ( bv = a->a_vals, j = 0; bv->bv_val != NULL; bv++, j++ ) {
int ret;
int rc;
const char *text;
rc = value_match( &ret, a->a_desc, mra->ma_rule,
SLAP_MR_ASSERTION_SYNTAX_MATCH,
bv, &mra->ma_value,
&text );
if( rc != LDAP_SUCCESS ) {
return rc;
}
if ( ret ) {
(*e_flags)[i][j] = 1;
}
}
}
return LDAP_SUCCESS;
}