static int dyngroup_response( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; adpair *ap = on->on_bi.bi_private; /* If we've been configured and the current response is * what we're looking for... */ if ( ap && op->o_tag == LDAP_REQ_COMPARE && rs->sr_err == LDAP_NO_SUCH_ATTRIBUTE ) { for (;ap;ap=ap->ap_next) { if ( op->oq_compare.rs_ava->aa_desc == ap->ap_mem ) { /* This compare is for one of the attributes we're * interested in. We'll use slapd's existing dyngroup * evaluator to get the answer we want. */ int cache = op->o_do_not_cache; op->o_do_not_cache = 1; rs->sr_err = backend_group( op, NULL, &op->o_req_ndn, &op->oq_compare.rs_ava->aa_value, NULL, ap->ap_uri ); op->o_do_not_cache = cache; switch ( rs->sr_err ) { case LDAP_SUCCESS: rs->sr_err = LDAP_COMPARE_TRUE; break; case LDAP_NO_SUCH_OBJECT: rs->sr_err = LDAP_COMPARE_FALSE; break; } break; } } } /* Default is to just fall through to the normal processing */ return SLAP_CB_CONTINUE; }
static int aci_group_member ( struct berval *subj, const struct berval *defgrpoc, const struct berval *defgrpat, Operation *op, Entry *e, int nmatch, regmatch_t *matches ) { struct berval subjdn; struct berval grpoc; struct berval grpat; ObjectClass *grp_oc = NULL; AttributeDescription *grp_ad = NULL; const char *text; int rc; /* format of string is "{group|role}/objectClassValue/groupAttrName" */ if ( acl_get_part( subj, 0, '/', &subjdn ) < 0 ) { return 0; } if ( acl_get_part( subj, 1, '/', &grpoc ) < 0 ) { grpoc = *defgrpoc; } if ( acl_get_part( subj, 2, '/', &grpat ) < 0 ) { grpat = *defgrpat; } rc = slap_bv2ad( &grpat, &grp_ad, &text ); if ( rc != LDAP_SUCCESS ) { rc = 0; goto done; } rc = 0; grp_oc = oc_bvfind( &grpoc ); if ( grp_oc != NULL && grp_ad != NULL ) { char buf[ ACI_BUF_SIZE ]; struct berval bv, ndn; AclRegexMatches amatches = { 0 }; amatches.dn_count = nmatch; memcpy( amatches.dn_data, matches, sizeof( amatches.dn_data ) ); bv.bv_len = sizeof( buf ) - 1; bv.bv_val = (char *)&buf; if ( acl_string_expand( &bv, &subjdn, &e->e_nname, NULL, &amatches ) ) { rc = LDAP_OTHER; goto done; } if ( dnNormalize( 0, NULL, NULL, &bv, &ndn, op->o_tmpmemctx ) == LDAP_SUCCESS ) { rc = ( backend_group( op, e, &ndn, &op->o_ndn, grp_oc, grp_ad ) == 0 ); slap_sl_free( ndn.bv_val, op->o_tmpmemctx ); } } done: return rc; }
static int dynlist_compare( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; Operation o = *op; Entry *e = NULL; dynlist_map_t *dlm; BackendDB *be; for ( ; dli != NULL; dli = dli->dli_next ) { for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad ) break; if ( dlm ) { /* This compare is for one of the attributes we're * interested in. We'll use slapd's existing dyngroup * evaluator to get the answer we want. */ BerVarray id = NULL, authz = NULL; o.o_do_not_cache = 1; if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS ) { /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( id ) && !be_isroot( op ) && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgAuthz, &authz, ACL_READ ) == LDAP_SUCCESS ) { rs->sr_err = slap_sasl_matches( op, authz, &o.o_ndn, &o.o_ndn ); ber_bvarray_free_x( authz, op->o_tmpmemctx ); if ( rs->sr_err != LDAP_SUCCESS ) { goto done; } } o.o_dn = *id; o.o_ndn = *id; o.o_groups = NULL; /* authz changed, invalidate cached groups */ } rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn, &o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad ); switch ( rs->sr_err ) { case LDAP_SUCCESS: rs->sr_err = LDAP_COMPARE_TRUE; break; case LDAP_NO_SUCH_OBJECT: /* NOTE: backend_group() returns noSuchObject * if op_ndn does not exist; however, since * dynamic list expansion means that the * member attribute is virtually present, the * non-existence of the asserted value implies * the assertion is FALSE rather than * UNDEFINED */ rs->sr_err = LDAP_COMPARE_FALSE; break; } done:; if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx ); return SLAP_CB_CONTINUE; } } be = select_backend( &o.o_req_ndn, 1 ); if ( !be || !be->be_search ) { return SLAP_CB_CONTINUE; } if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL ) { return SLAP_CB_CONTINUE; } /* check for dynlist objectClass; done if not found */ dli = (dynlist_info_t *)on->on_bi.bi_private; while ( dli != NULL && !is_entry_objectclass_or_sub( e, dli->dli_oc ) ) { dli = dli->dli_next; } if ( dli == NULL ) { goto release; } if ( ad_dgIdentity ) { Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity ); if ( id ) { Attribute *authz; /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op ) && ( authz = attrs_find( e->e_attrs, ad_dgAuthz ) ) ) { if ( slap_sasl_matches( op, authz->a_nvals, &o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS ) { goto release; } } o.o_dn = id->a_vals[0]; o.o_ndn = id->a_nvals[0]; o.o_groups = NULL; } } /* generate dynamic list with dynlist_response() and compare */ { SlapReply r = { REP_SEARCH }; dynlist_cc_t dc = { { 0, dynlist_sc_compare_entry, 0, 0 }, 0 }; AttributeName an[2]; dc.dc_ava = op->orc_ava; dc.dc_res = &rs->sr_err; o.o_callback = (slap_callback *) &dc; o.o_tag = LDAP_REQ_SEARCH; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; o.ors_filterstr = *slap_filterstr_objectClass_pres; o.ors_filter = (Filter *) slap_filter_objectClass_pres; o.ors_scope = LDAP_SCOPE_BASE; o.ors_deref = LDAP_DEREF_NEVER; an[0].an_name = op->orc_ava->aa_desc->ad_cname; an[0].an_desc = op->orc_ava->aa_desc; BER_BVZERO( &an[1].an_name ); o.ors_attrs = an; o.ors_attrsonly = 0; o.o_acl_priv = ACL_COMPARE; o.o_bd = be; (void)be->be_search( &o, &r ); if ( o.o_dn.bv_val != op->o_dn.bv_val ) { slap_op_groups_free( &o ); } } release:; if ( e != NULL ) { overlay_entry_release_ov( &o, e, 0, on ); } return SLAP_CB_CONTINUE; }
static int limits_get( Operation *op, struct slap_limits_set **limit ) { static struct berval empty_dn = BER_BVC( "" ); struct slap_limits **lm; struct berval *ndns[2]; assert( op != NULL ); assert( limit != NULL ); ndns[0] = &op->o_ndn; ndns[1] = &op->o_req_ndn; Debug( LDAP_DEBUG_TRACE, "==> limits_get: %s self=\"%s\" this=\"%s\"\n", op->o_log_prefix, BER_BVISNULL( ndns[0] ) ? "[anonymous]" : ndns[0]->bv_val, BER_BVISNULL( ndns[1] ) ? "" : ndns[1]->bv_val ); /* * default values */ *limit = &op->o_bd->be_def_limit; if ( op->o_bd->be_limits == NULL ) { return( 0 ); } for ( lm = op->o_bd->be_limits; lm[0] != NULL; lm++ ) { unsigned style = lm[0]->lm_flags & SLAP_LIMITS_MASK; unsigned type = lm[0]->lm_flags & SLAP_LIMITS_TYPE_MASK; unsigned isthis = type == SLAP_LIMITS_TYPE_THIS; struct berval *ndn = ndns[isthis]; if ( style == SLAP_LIMITS_ANY ) goto found_any; if ( BER_BVISEMPTY( ndn ) ) { if ( style == SLAP_LIMITS_ANONYMOUS ) goto found_nodn; if ( !isthis ) continue; ndn = &empty_dn; } switch ( style ) { case SLAP_LIMITS_EXACT: if ( type == SLAP_LIMITS_TYPE_GROUP ) { int rc = backend_group( op, NULL, &lm[0]->lm_pat, ndn, lm[0]->lm_group_oc, lm[0]->lm_group_ad ); if ( rc == 0 ) { goto found_group; } } else { if ( dn_match( &lm[0]->lm_pat, ndn ) ) { goto found_dn; } } break; case SLAP_LIMITS_ONE: case SLAP_LIMITS_SUBTREE: case SLAP_LIMITS_CHILDREN: { ber_len_t d; /* ndn shorter than lm_pat */ if ( ndn->bv_len < lm[0]->lm_pat.bv_len ) { break; } d = ndn->bv_len - lm[0]->lm_pat.bv_len; if ( d == 0 ) { /* allow exact match for SUBTREE only */ if ( style != SLAP_LIMITS_SUBTREE ) { break; } } else { /* check for unescaped rdn separator */ if ( !DN_SEPARATOR( ndn->bv_val[d - 1] ) ) { break; } } /* check that ndn ends with lm_pat */ if ( strcmp( lm[0]->lm_pat.bv_val, &ndn->bv_val[d] ) != 0 ) { break; } /* in case of ONE, require exactly one rdn below lm_pat */ if ( style == SLAP_LIMITS_ONE ) { if ( dn_rdnlen( NULL, ndn ) != d - 1 ) { break; } } goto found_dn; } case SLAP_LIMITS_REGEX: if ( regexec( &lm[0]->lm_regex, ndn->bv_val, 0, NULL, 0 ) == 0 ) { goto found_dn; } break; case SLAP_LIMITS_ANONYMOUS: break; case SLAP_LIMITS_USERS: found_nodn: Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=%s match=%s\n", dn_source[isthis], limits2str( style ), 0 ); found_any: *limit = &lm[0]->lm_limits; return( 0 ); found_dn: Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=%s match=%s dn=\"%s\"\n", dn_source[isthis], limits2str( style ), lm[0]->lm_pat.bv_val ); *limit = &lm[0]->lm_limits; return( 0 ); found_group: Debug( LDAP_DEBUG_TRACE, "<== limits_get: type=GROUP match=EXACT " "dn=\"%s\" oc=\"%s\" ad=\"%s\"\n", lm[0]->lm_pat.bv_val, lm[0]->lm_group_oc->soc_cname.bv_val, lm[0]->lm_group_ad->ad_cname.bv_val ); *limit = &lm[0]->lm_limits; return( 0 ); default: assert( 0 ); /* unreachable */ return( -1 ); } } return( 0 ); }
static int dynlist_compare( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dynlist_info_t *dli = (dynlist_info_t *)on->on_bi.bi_private; Operation o = *op; Entry *e = NULL; dynlist_map_t *dlm; for ( ; dli != NULL; dli = dli->dli_next ) { for ( dlm = dli->dli_dlm; dlm; dlm = dlm->dlm_next ) if ( op->oq_compare.rs_ava->aa_desc == dlm->dlm_member_ad ) break; if ( dli->dli_dlm && dlm ) { /* This compare is for one of the attributes we're * interested in. We'll use slapd's existing dyngroup * evaluator to get the answer we want. */ BerVarray id = NULL, authz = NULL; o.o_do_not_cache = 1; if ( ad_dgIdentity && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgIdentity, &id, ACL_READ ) == LDAP_SUCCESS ) { /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( id ) && !be_isroot( op ) && backend_attribute( &o, NULL, &o.o_req_ndn, ad_dgAuthz, &authz, ACL_READ ) == LDAP_SUCCESS ) { rs->sr_err = slap_sasl_matches( op, authz, &o.o_ndn, &o.o_ndn ); ber_bvarray_free_x( authz, op->o_tmpmemctx ); if ( rs->sr_err != LDAP_SUCCESS ) { goto done; } } o.o_dn = *id; o.o_ndn = *id; o.o_groups = NULL; /* authz changed, invalidate cached groups */ } rs->sr_err = backend_group( &o, NULL, &o.o_req_ndn, &o.oq_compare.rs_ava->aa_value, dli->dli_oc, dli->dli_ad ); switch ( rs->sr_err ) { case LDAP_SUCCESS: rs->sr_err = LDAP_COMPARE_TRUE; break; case LDAP_NO_SUCH_OBJECT: /* NOTE: backend_group() returns noSuchObject * if op_ndn does not exist; however, since * dynamic list expansion means that the * member attribute is virtually present, the * non-existence of the asserted value implies * the assertion is FALSE rather than * UNDEFINED */ rs->sr_err = LDAP_COMPARE_FALSE; break; } done:; if ( id ) ber_bvarray_free_x( id, o.o_tmpmemctx ); return SLAP_CB_CONTINUE; } } if ( overlay_entry_get_ov( &o, &o.o_req_ndn, NULL, NULL, 0, &e, on ) != LDAP_SUCCESS || e == NULL ) { return SLAP_CB_CONTINUE; } if ( ad_dgIdentity ) { Attribute *id = attrs_find( e->e_attrs, ad_dgIdentity ); if ( id ) { Attribute *authz; /* if not rootdn and dgAuthz is present, * check if user can be authorized as dgIdentity */ if ( ad_dgAuthz && !BER_BVISEMPTY( &id->a_nvals[0] ) && !be_isroot( op ) && ( authz = attrs_find( e->e_attrs, ad_dgAuthz ) ) ) { if ( slap_sasl_matches( op, authz->a_nvals, &o.o_ndn, &o.o_ndn ) != LDAP_SUCCESS ) { goto release; } } o.o_dn = id->a_vals[0]; o.o_ndn = id->a_nvals[0]; o.o_groups = NULL; } } dli = (dynlist_info_t *)on->on_bi.bi_private; for ( ; dli != NULL && rs->sr_err != LDAP_COMPARE_TRUE; dli = dli->dli_next ) { Attribute *a; slap_callback cb; SlapReply r = { REP_SEARCH }; AttributeName an[2]; int rc; dynlist_sc_t dlc = { 0 }; if ( !is_entry_objectclass_or_sub( e, dli->dli_oc )) continue; /* if the entry has the right objectClass, generate * the dynamic list and compare */ dlc.dlc_dli = dli; cb.sc_private = &dlc; cb.sc_response = dynlist_sc_save_entry; cb.sc_cleanup = NULL; cb.sc_next = NULL; o.o_callback = &cb; o.o_tag = LDAP_REQ_SEARCH; o.ors_limit = NULL; o.ors_tlimit = SLAP_NO_LIMIT; o.ors_slimit = SLAP_NO_LIMIT; o.o_bd = select_backend( &o.o_req_ndn, 1 ); if ( !o.o_bd || !o.o_bd->be_search ) { goto release; } o.ors_filterstr = *slap_filterstr_objectClass_pres; o.ors_filter = (Filter *) slap_filter_objectClass_pres; o.ors_scope = LDAP_SCOPE_BASE; o.ors_deref = LDAP_DEREF_NEVER; an[0].an_name = op->orc_ava->aa_desc->ad_cname; an[0].an_desc = op->orc_ava->aa_desc; BER_BVZERO( &an[1].an_name ); o.ors_attrs = an; o.ors_attrsonly = 0; o.o_acl_priv = ACL_COMPARE; rc = o.o_bd->be_search( &o, &r ); if ( o.o_dn.bv_val != op->o_dn.bv_val ) { slap_op_groups_free( &o ); } if ( rc != 0 ) { goto release; } if ( dlc.dlc_e != NULL ) { r.sr_entry = dlc.dlc_e; } if ( r.sr_err != LDAP_SUCCESS || r.sr_entry == NULL ) { /* error? */ goto release; } for ( a = attrs_find( r.sr_entry->e_attrs, op->orc_ava->aa_desc ); a != NULL; a = attrs_find( a->a_next, op->orc_ava->aa_desc ) ) { /* if we're here, we got a match... */ rs->sr_err = LDAP_COMPARE_FALSE; if ( attr_valfind( a, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, &op->orc_ava->aa_value, NULL, op->o_tmpmemctx ) == 0 ) { rs->sr_err = LDAP_COMPARE_TRUE; break; } } if ( r.sr_flags & REP_ENTRY_MUSTBEFREED ) { entry_free( r.sr_entry ); } } release:; if ( e != NULL ) { overlay_entry_release_ov( &o, e, 0, on ); } return SLAP_CB_CONTINUE; }