mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
fbc11bd16a
to back-bdb, back-ldbm and back-sql (the latter with limitations); - added handling of ":dn" attributes to extended rfc2254 filters and to matched value filter - altered the behavior of get_mra() when a matching rule is given: now it checks whether it is compatible with the attribute syntax and, in case it is, the given mr is used. In case of no type, the check is delayed when filtering
294 lines
7.0 KiB
C
294 lines
7.0 KiB
C
/* $OpenLDAP$ */
|
|
/*
|
|
* Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
|
|
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file
|
|
*/
|
|
/* mra.c - routines for dealing with extensible matching rule assertions */
|
|
|
|
#include "portable.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <ac/string.h>
|
|
#include <ac/socket.h>
|
|
|
|
#include "slap.h"
|
|
|
|
void
|
|
mra_free(
|
|
MatchingRuleAssertion *mra,
|
|
int freeit
|
|
)
|
|
{
|
|
ch_free( mra->ma_value.bv_val );
|
|
if ( freeit ) {
|
|
ch_free( (char *) mra );
|
|
}
|
|
}
|
|
|
|
int
|
|
get_mra(
|
|
BerElement *ber,
|
|
MatchingRuleAssertion **mra,
|
|
const char **text
|
|
)
|
|
{
|
|
int rc;
|
|
ber_tag_t tag, rtag;
|
|
ber_len_t length;
|
|
struct berval type = { 0, NULL }, value;
|
|
MatchingRuleAssertion *ma;
|
|
|
|
ma = ch_malloc( sizeof( MatchingRuleAssertion ) );
|
|
ma->ma_rule = NULL;
|
|
ma->ma_rule_text.bv_len = 0;
|
|
ma->ma_rule_text.bv_val = NULL;
|
|
ma->ma_desc = NULL;
|
|
ma->ma_dnattrs = 0;
|
|
ma->ma_value.bv_len = 0;
|
|
ma->ma_value.bv_val = NULL;
|
|
|
|
rtag = ber_scanf( ber, "{t", &tag );
|
|
|
|
if( rtag == LBER_ERROR ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR,
|
|
"get_mra: ber_scanf (\"{t\") failure\n", 0, 0, 0 );
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Error parsing matching rule assertion";
|
|
mra_free( ma, 1 );
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
|
|
if ( tag == LDAP_FILTER_EXT_OID ) {
|
|
rtag = ber_scanf( ber, "m", &ma->ma_rule_text );
|
|
if ( rtag == LBER_ERROR ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR,
|
|
"get_mra: ber_scanf(\"o\") failure.\n", 0, 0, 0 );
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf for mr\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Error parsing matching rule in matching rule assertion";
|
|
mra_free( ma, 1 );
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
|
|
rtag = ber_scanf( ber, "t", &tag );
|
|
if( rtag == LBER_ERROR ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR,
|
|
"get_mra: ber_scanf (\"t\") failure\n", 0, 0, 0 );
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Error parsing matching rule assertion";
|
|
mra_free( ma, 1 );
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
}
|
|
|
|
if ( tag == LDAP_FILTER_EXT_TYPE ) {
|
|
rtag = ber_scanf( ber, "m", &type );
|
|
if ( rtag == LBER_ERROR ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR,
|
|
"get_mra: ber_scanf (\"o\") failure.\n", 0, 0, 0 );
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf for ad\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Error parsing attribute description in matching rule assertion";
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
|
|
rtag = ber_scanf( ber, "t", &tag );
|
|
if( rtag == LBER_ERROR ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR,
|
|
"get_mra: ber_scanf (\"t\") failure.\n", 0, 0, 0 );
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Error parsing matching rule assertion";
|
|
mra_free( ma, 1 );
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
}
|
|
|
|
if ( tag != LDAP_FILTER_EXT_VALUE ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR,
|
|
"get_mra: ber_scanf missing value\n", 0, 0, 0 );
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf missing value\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Missing value in matching rule assertion";
|
|
mra_free( ma, 1 );
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
|
|
rtag = ber_scanf( ber, "m", &value );
|
|
|
|
if( rtag == LBER_ERROR ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR,
|
|
"get_mra: ber_scanf (\"o\") failure.\n", 0, 0, 0 );
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Error decoding value in matching rule assertion";
|
|
mra_free( ma, 1 );
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
|
|
tag = ber_peek_tag( ber, &length );
|
|
|
|
if ( tag == LDAP_FILTER_EXT_DNATTRS ) {
|
|
rtag = ber_scanf( ber, "b}", &ma->ma_dnattrs );
|
|
} else {
|
|
rtag = ber_scanf( ber, "}" );
|
|
}
|
|
|
|
if( rtag == LBER_ERROR ) {
|
|
#ifdef NEW_LOGGING
|
|
LDAP_LOG( OPERATION, ERR, "get_mra: ber_scanf failure\n", 0, 0, 0);
|
|
#else
|
|
Debug( LDAP_DEBUG_ANY, " get_mra ber_scanf\n", 0, 0, 0 );
|
|
#endif
|
|
|
|
*text = "Error decoding dnattrs matching rule assertion";
|
|
mra_free( ma, 1 );
|
|
return SLAPD_DISCONNECT;
|
|
}
|
|
|
|
#ifndef SLAP_X_MRA_MATCH_DNATTRS
|
|
/*
|
|
* Let's try to implement it
|
|
*/
|
|
if( ma->ma_dnattrs ) {
|
|
*text = "matching with \":dn\" not supported";
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
#endif /* !SLAP_X_MRA_MATCH_DNATTRS */
|
|
|
|
if( type.bv_val != NULL ) {
|
|
rc = slap_bv2ad( &type, &ma->ma_desc, text );
|
|
if( rc != LDAP_SUCCESS ) {
|
|
mra_free( ma, 1 );
|
|
return rc;
|
|
}
|
|
|
|
#ifndef SLAP_X_MRA_MATCH_DNATTRS
|
|
} else {
|
|
*text = "matching without attribute description rule not supported";
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
#endif /* !SLAP_X_MRA_MATCH_DNATTRS */
|
|
}
|
|
|
|
if( ma->ma_rule_text.bv_val != NULL ) {
|
|
ma->ma_rule = mr_bvfind( &ma->ma_rule_text );
|
|
if( ma->ma_rule == NULL ) {
|
|
mra_free( ma, 1 );
|
|
*text = "matching rule not recognized";
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* FIXME: is it correct that ma->ma_rule_text, if present,
|
|
* is looked-up, checked, and then replaced by the sat_equality
|
|
* of the given attribute? I'd rather do smtg like use
|
|
* the attribute's equality rule only if no matching rule
|
|
* was given, otherwise I don't see any extension ...
|
|
*/
|
|
|
|
#if 1
|
|
if ( ma->ma_rule == NULL ) {
|
|
#ifdef SLAP_X_MRA_MATCH_DNATTRS
|
|
/*
|
|
* Need either type or rule ...
|
|
*/
|
|
if ( ma->ma_desc == NULL ) {
|
|
mra_free( ma, 1 );
|
|
*text = "matching rule not recognized";
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
#endif /* !SLAP_X_MRA_MATCH_DNATTRS */
|
|
|
|
if ( ma->ma_desc->ad_type->sat_equality != NULL &&
|
|
ma->ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT )
|
|
{
|
|
/* no matching rule was provided, use the attribute's
|
|
equality rule if it supports extensible matching. */
|
|
ma->ma_rule = ma->ma_desc->ad_type->sat_equality;
|
|
|
|
} else {
|
|
mra_free( ma, 1 );
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
}
|
|
#else
|
|
if( ma->ma_desc != NULL &&
|
|
ma->ma_desc->ad_type->sat_equality != NULL &&
|
|
ma->ma_desc->ad_type->sat_equality->smr_usage & SLAP_MR_EXT )
|
|
{
|
|
/* no matching rule was provided, use the attribute's
|
|
equality rule if it supports extensible matching. */
|
|
ma->ma_rule = ma->ma_desc->ad_type->sat_equality;
|
|
|
|
} else {
|
|
mra_free( ma, 1 );
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
#endif
|
|
|
|
#ifdef SLAP_X_MRA_MATCH_DNATTRS
|
|
if ( ma->ma_desc != NULL ) {
|
|
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
|
|
/* check to see if the matching rule is appropriate for
|
|
the syntax of the attribute. This check will need
|
|
to be extended to support other kinds of extensible
|
|
matching rules */
|
|
if( strcmp( ma->ma_rule->smr_syntax->ssyn_oid,
|
|
ma->ma_desc->ad_type->sat_syntax->ssyn_oid ) != 0 )
|
|
{
|
|
mra_free( ma, 1 );
|
|
return LDAP_INAPPROPRIATE_MATCHING;
|
|
}
|
|
|
|
/*
|
|
* OK, if no matching rule, normalize for equality, otherwise
|
|
* normalize for the matching rule.
|
|
*/
|
|
rc = value_validate_normalize( ma->ma_desc, SLAP_MR_EQUALITY,
|
|
&value, &ma->ma_value, text );
|
|
#ifdef SLAP_X_MRA_MATCH_DNATTRS
|
|
} else {
|
|
/*
|
|
* Need to normalize, but how?
|
|
*/
|
|
ma->ma_value = value;
|
|
rc = value_validate( ma->ma_rule, &ma->ma_value, text );
|
|
|
|
}
|
|
#endif /* SLAP_X_MRA_MATCH_DNATTRS */
|
|
|
|
if( rc != LDAP_SUCCESS ) {
|
|
mra_free( ma, 1 );
|
|
return rc;
|
|
}
|
|
|
|
*mra = ma;
|
|
return LDAP_SUCCESS;
|
|
}
|
|
|