int dnPretty( Syntax *syntax, struct berval *val, struct berval *out, void *ctx) { assert( val != NULL ); assert( out != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dnPretty: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 ); if ( val->bv_len == 0 ) { ber_dupbv_x( out, val, ctx ); } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { return LDAP_INVALID_SYNTAX; } else { LDAPDN dn = NULL; int rc; /* FIXME: should be liberal in what we accept */ rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } /* FIXME: not sure why the default isn't pretty */ /* RE: the default is the form that is used as * an internal representation; the pretty form * is a variant */ rc = ldap_dn2bv_x( dn, out, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); ldap_dnfree_x( dn, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } Debug( LDAP_DEBUG_TRACE, "<<< dnPretty: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 ); return LDAP_SUCCESS; }
int dnNormalize( slap_mask_t use, Syntax *syntax, MatchingRule *mr, struct berval *val, struct berval *out, void *ctx) { assert( val != NULL ); assert( out != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dnNormalize: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 ); if ( val->bv_len != 0 ) { LDAPDN dn = NULL; int rc; /* * Go to structural representation */ rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } /* * Back to string representation */ rc = ldap_dn2bv_x( dn, out, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); ldap_dnfree_x( dn, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } } else { ber_dupbv_x( out, val, ctx ); } Debug( LDAP_DEBUG_TRACE, "<<< dnNormalize: <%s>\n", out->bv_val ? out->bv_val : "", 0, 0 ); return LDAP_SUCCESS; }
/* Rewrite an LDAP DN in DER form * Input must be valid DN, therefore no error checking is done here. */ static int autoca_dnbv2der( Operation *op, struct berval *bv, struct berval *der ) { BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; LDAPDN dn; LDAPRDN rdn; LDAPAVA *ava; AttributeDescription *ad; int irdn, iava; ldap_bv2dn_x( bv, &dn, LDAP_DN_FORMAT_LDAP, op->o_tmpmemctx ); ber_init2( ber, NULL, LBER_USE_DER ); ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); /* count RDNs, we need them in reverse order */ for (irdn = 0; dn[irdn]; irdn++); irdn--; /* DN is a SEQuence of RDNs */ ber_start_seq( ber, LBER_SEQUENCE ); for (; irdn >=0; irdn--) { /* RDN is a SET of AVAs */ ber_start_set( ber, LBER_SET ); rdn = dn[irdn]; for (iava = 0; rdn[iava]; iava++) { const char *text; char oid[1024]; struct berval bvo = { sizeof(oid), oid }; struct berval bva; /* AVA is a SEQuence of attr and value */ ber_start_seq( ber, LBER_SEQUENCE ); ava = rdn[iava]; ad = NULL; slap_bv2ad( &ava->la_attr, &ad, &text ); ber_str2bv( ad->ad_type->sat_oid, 0, 0, &bva ); ber_encode_oid( &bva, &bvo ); ber_put_berval( ber, &bvo, LBER_TAG_OID ); ber_put_berval( ber, &ava->la_value, LBER_TAG_UTF8 ); ber_put_seq( ber ); } ber_put_set( ber ); } ber_put_seq( ber ); ber_flatten2( ber, der, 0 ); ldap_dnfree_x( dn, op->o_tmpmemctx ); return 0; }
int dnPrettyNormalDN( Syntax *syntax, struct berval *val, LDAPDN *dn, int flags, void *ctx ) { assert( val != NULL ); assert( dn != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dn%sDN: <%s>\n", flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal", val->bv_val ? val->bv_val : "", 0 ); if ( val->bv_len == 0 ) { return LDAP_SUCCESS; } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { return LDAP_INVALID_SYNTAX; } else { int rc; /* FIXME: should be liberal in what we accept */ rc = ldap_bv2dn_x( val, dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( *dn, flags, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( *dn, ctx ); *dn = NULL; return LDAP_INVALID_SYNTAX; } } Debug( LDAP_DEBUG_TRACE, "<<< dn%sDN\n", flags == SLAP_LDAPDN_PRETTY ? "Pretty" : "Normal", 0, 0 ); return LDAP_SUCCESS; }
static int test_mra_filter( Operation *op, Entry *e, MatchingRuleAssertion *mra ) { Attribute *a; void *memctx; BER_MEMFREE_FN *memfree; #ifdef LDAP_COMP_MATCH int i, num_attr_vals = 0; #endif if ( op == NULL ) { memctx = NULL; memfree = slap_sl_free; } else { memctx = op->o_tmpmemctx; memfree = op->o_tmpfree; } if ( mra->ma_desc ) { /* * if ma_desc is available, then we're filtering for * one attribute, and SEARCH permissions can be checked * directly. */ if ( !access_allowed( op, e, mra->ma_desc, &mra->ma_value, ACL_SEARCH, NULL ) ) { return LDAP_INSUFFICIENT_ACCESS; } if ( mra->ma_desc == slap_schema.si_ad_entryDN ) { int ret, rc; const char *text; rc = value_match( &ret, slap_schema.si_ad_entryDN, mra->ma_rule, SLAP_MR_EXT, &e->e_nname, &mra->ma_value, &text ); if( rc != LDAP_SUCCESS ) return rc; if ( ret == 0 ) return LDAP_COMPARE_TRUE; return LDAP_COMPARE_FALSE; } for ( a = attrs_find( e->e_attrs, mra->ma_desc ); a != NULL; a = attrs_find( a->a_next, mra->ma_desc ) ) { struct berval *bv; int normalize_attribute = 0; #ifdef LDAP_COMP_MATCH /* Component Matching */ if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) { num_attr_vals = 0; if ( !a->a_comp_data ) { num_attr_vals = a->a_numvals; if ( num_attr_vals <= 0 ) { /* no attribute value */ return LDAP_INAPPROPRIATE_MATCHING; } num_attr_vals++; /* following malloced will be freed by comp_tree_free () */ a->a_comp_data = SLAP_MALLOC( sizeof( ComponentData ) + sizeof( ComponentSyntaxInfo* )*num_attr_vals ); if ( !a->a_comp_data ) return LDAP_NO_MEMORY; a->a_comp_data->cd_tree = (ComponentSyntaxInfo**) ((char*)a->a_comp_data + sizeof(ComponentData)); a->a_comp_data->cd_tree[num_attr_vals - 1] = (ComponentSyntaxInfo*) NULL; a->a_comp_data->cd_mem_op = nibble_mem_allocator( 1024*16, 1024 ); } } #endif /* If ma_rule is not the same as the attribute's * normal rule, then we can't use the a_nvals. */ if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) { bv = a->a_nvals; } else { bv = a->a_vals; normalize_attribute = 1; } #ifdef LDAP_COMP_MATCH i = 0; #endif for ( ; !BER_BVISNULL( bv ); bv++ ) { int ret; int rc; const char *text; #ifdef LDAP_COMP_MATCH if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) { /* Check if decoded component trees are already linked */ if ( num_attr_vals ) { a->a_comp_data->cd_tree[i] = attr_converter( a, a->a_desc->ad_type->sat_syntax, bv ); } /* decoding error */ if ( !a->a_comp_data->cd_tree[i] ) { return LDAP_OPERATIONS_ERROR; } rc = value_match( &ret, a->a_desc, mra->ma_rule, SLAP_MR_COMPONENT, (struct berval*)a->a_comp_data->cd_tree[i++], (void*)mra, &text ); } else #endif { struct berval nbv = BER_BVNULL; if ( normalize_attribute && mra->ma_rule->smr_normalize ) { /* Document: RFC 4511 4.5.1. Search Request ... If the type field is present and the matchingRule is present, the matchValue is compared against entry attributes of the specified type. In this case, the matchingRule MUST be one suitable for use with the specified type (see [RFC4517]), otherwise the filter item is Undefined. In this case, since the matchingRule requires the assertion value to be normalized, we normalize the attribute value according to the syntax of the matchingRule. This should likely be done inside value_match(), by passing the appropriate flags, but this is not done at present. See ITS#3406. */ if ( mra->ma_rule->smr_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, mra->ma_rule->smr_syntax, mra->ma_rule, bv, &nbv, memctx ) != LDAP_SUCCESS ) { /* FIXME: stop processing? */ continue; } } else { nbv = *bv; } rc = value_match( &ret, a->a_desc, mra->ma_rule, SLAP_MR_EXT, &nbv, &mra->ma_value, &text ); if ( nbv.bv_val != bv->bv_val ) { memfree( nbv.bv_val, memctx ); } } if ( rc != LDAP_SUCCESS ) return rc; if ( ret == 0 ) return LDAP_COMPARE_TRUE; } } } else { /* * No attribute description: test all */ for ( a = e->e_attrs; a != NULL; a = a->a_next ) { struct berval *bv, value; const char *text = NULL; int rc; int normalize_attribute = 0; /* check if matching is appropriate */ if ( !mr_usable_with_at( mra->ma_rule, a->a_desc->ad_type ) ) { continue; } /* normalize for equality */ rc = asserted_value_validate_normalize( a->a_desc, mra->ma_rule, SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, &mra->ma_value, &value, &text, memctx ); if ( rc != LDAP_SUCCESS ) continue; /* check search access */ if ( !access_allowed( op, e, a->a_desc, &value, ACL_SEARCH, NULL ) ) { memfree( value.bv_val, memctx ); continue; } #ifdef LDAP_COMP_MATCH /* Component Matching */ if ( mra->ma_cf && mra->ma_rule->smr_usage & SLAP_MR_COMPONENT ) { int ret; rc = value_match( &ret, a->a_desc, mra->ma_rule, SLAP_MR_COMPONENT, (struct berval*)a, (void*)mra, &text ); if ( rc != LDAP_SUCCESS ) break; if ( ret == 0 ) { rc = LDAP_COMPARE_TRUE; break; } } #endif /* check match */ if ( mra->ma_rule == a->a_desc->ad_type->sat_equality ) { bv = a->a_nvals; } else { bv = a->a_vals; normalize_attribute = 1; } for ( ; !BER_BVISNULL( bv ); bv++ ) { int ret; struct berval nbv = BER_BVNULL; if ( normalize_attribute && mra->ma_rule->smr_normalize ) { /* see comment above */ if ( mra->ma_rule->smr_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, mra->ma_rule->smr_syntax, mra->ma_rule, bv, &nbv, memctx ) != LDAP_SUCCESS ) { /* FIXME: stop processing? */ continue; } } else { nbv = *bv; } rc = value_match( &ret, a->a_desc, mra->ma_rule, SLAP_MR_EXT, &nbv, &value, &text ); if ( nbv.bv_val != bv->bv_val ) { memfree( nbv.bv_val, memctx ); } if ( rc != LDAP_SUCCESS ) break; if ( ret == 0 ) { rc = LDAP_COMPARE_TRUE; break; } } memfree( value.bv_val, memctx ); if ( rc != LDAP_SUCCESS ) return rc; } } /* check attrs in DN AVAs if required */ if ( mra->ma_dnattrs && !BER_BVISEMPTY( &e->e_nname ) ) { LDAPDN dn = NULL; int iRDN, iAVA; int rc; /* parse and pretty the dn */ rc = dnPrettyDN( NULL, &e->e_name, &dn, memctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } /* for each AVA of each RDN ... */ for ( iRDN = 0; dn[ iRDN ]; iRDN++ ) { LDAPRDN rdn = dn[ iRDN ]; for ( iAVA = 0; rdn[ iAVA ]; iAVA++ ) { LDAPAVA *ava = rdn[ iAVA ]; struct berval *bv = &ava->la_value, value = BER_BVNULL, nbv = BER_BVNULL; AttributeDescription *ad = (AttributeDescription *)ava->la_private; int ret; const char *text; assert( ad != NULL ); if ( mra->ma_desc ) { /* have a mra type? check for subtype */ if ( !is_ad_subtype( ad, mra->ma_desc ) ) { continue; } value = mra->ma_value; } else { const char *text = NULL; /* check if matching is appropriate */ if ( !mr_usable_with_at( mra->ma_rule, ad->ad_type ) ) { continue; } /* normalize for equality */ rc = asserted_value_validate_normalize( ad, mra->ma_rule, SLAP_MR_EXT|SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, &mra->ma_value, &value, &text, memctx ); if ( rc != LDAP_SUCCESS ) continue; /* check search access */ if ( !access_allowed( op, e, ad, &value, ACL_SEARCH, NULL ) ) { memfree( value.bv_val, memctx ); continue; } } if ( mra->ma_rule->smr_normalize ) { /* see comment above */ if ( mra->ma_rule->smr_normalize( SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX, mra->ma_rule->smr_syntax, mra->ma_rule, bv, &nbv, memctx ) != LDAP_SUCCESS ) { /* FIXME: stop processing? */ rc = LDAP_SUCCESS; ret = -1; goto cleanup; } } else { nbv = *bv; } /* check match */ rc = value_match( &ret, ad, mra->ma_rule, SLAP_MR_EXT, &nbv, &value, &text ); cleanup:; if ( !BER_BVISNULL( &value ) && value.bv_val != mra->ma_value.bv_val ) { memfree( value.bv_val, memctx ); } if ( !BER_BVISNULL( &nbv ) && nbv.bv_val != bv->bv_val ) { memfree( nbv.bv_val, memctx ); } if ( rc == LDAP_SUCCESS && ret == 0 ) rc = LDAP_COMPARE_TRUE; if ( rc != LDAP_SUCCESS ) { ldap_dnfree_x( dn, memctx ); return rc; } } } ldap_dnfree_x( dn, memctx ); } return LDAP_COMPARE_FALSE; }
/* * Combination of both dnPretty and dnNormalize */ int dnPrettyNormal( Syntax *syntax, struct berval *val, struct berval *pretty, struct berval *normal, void *ctx) { assert( val != NULL ); assert( pretty != NULL ); assert( normal != NULL ); Debug( LDAP_DEBUG_TRACE, ">>> dnPrettyNormal: <%s>\n", val->bv_val ? val->bv_val : "", 0, 0 ); if ( val->bv_len == 0 ) { ber_dupbv_x( pretty, val, ctx ); ber_dupbv_x( normal, val, ctx ); } else if ( val->bv_len > SLAP_LDAPDN_MAXLEN ) { /* too big */ return LDAP_INVALID_SYNTAX; } else { LDAPDN dn = NULL; int rc; pretty->bv_val = NULL; normal->bv_val = NULL; pretty->bv_len = 0; normal->bv_len = 0; /* FIXME: should be liberal in what we accept */ rc = ldap_bv2dn_x( val, &dn, LDAP_DN_FORMAT_LDAP, ctx ); if ( rc != LDAP_SUCCESS ) { return LDAP_INVALID_SYNTAX; } assert( strlen( val->bv_val ) == val->bv_len ); /* * Schema-aware rewrite */ if ( LDAPDN_rewrite( dn, SLAP_LDAPDN_PRETTY, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } rc = ldap_dn2bv_x( dn, pretty, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); if ( rc != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); return LDAP_INVALID_SYNTAX; } if ( LDAPDN_rewrite( dn, 0, ctx ) != LDAP_SUCCESS ) { ldap_dnfree_x( dn, ctx ); ber_memfree_x( pretty->bv_val, ctx ); pretty->bv_val = NULL; pretty->bv_len = 0; return LDAP_INVALID_SYNTAX; } rc = ldap_dn2bv_x( dn, normal, LDAP_DN_FORMAT_LDAPV3 | LDAP_DN_PRETTY, ctx ); ldap_dnfree_x( dn, ctx ); if ( rc != LDAP_SUCCESS ) { ber_memfree_x( pretty->bv_val, ctx ); pretty->bv_val = NULL; pretty->bv_len = 0; return LDAP_INVALID_SYNTAX; } } Debug( LDAP_DEBUG_TRACE, "<<< dnPrettyNormal: <%s>, <%s>\n", pretty->bv_val ? pretty->bv_val : "", normal->bv_val ? normal->bv_val : "", 0 ); return LDAP_SUCCESS; }