int ad_inlist( AttributeDescription *desc, AttributeName *attrs ) { if (! attrs ) return 0; for( ; attrs->an_name.bv_val; attrs++ ) { AttributeType *a; ObjectClass *oc; if ( attrs->an_desc ) { int lr; if ( desc == attrs->an_desc ) { return 1; } /* * EXTENSION: if requested description is preceeded by * a '-' character, do not match on subtypes. */ if ( attrs->an_name.bv_val[0] == '-' ) { continue; } /* Is this a subtype of the requested attr? */ for (a = desc->ad_type; a; a=a->sat_sup) { if ( a == attrs->an_desc->ad_type ) break; } if ( !a ) { continue; } /* Does desc support all the requested flags? */ lr = desc->ad_tags.bv_len ? SLAP_DESC_TAG_RANGE : 0; if(( attrs->an_desc->ad_flags & (desc->ad_flags | lr)) != attrs->an_desc->ad_flags ) { continue; } /* Do the descs have compatible tags? */ if ( attrs->an_desc->ad_tags.bv_len == 0 ) { return 1; } if ( desc->ad_tags.bv_len == 0) { continue; } if ( is_ad_subtags( &desc->ad_tags, &attrs->an_desc->ad_tags ) ) { return 1; } continue; } if ( ber_bvccmp( &attrs->an_name, '*' ) ) { if ( !is_at_operational( desc->ad_type ) ) { return 1; } continue; } if ( ber_bvccmp( &attrs->an_name, '+' ) ) { if ( is_at_operational( desc->ad_type ) ) { return 1; } continue; } /* * EXTENSION: see if requested description is @objectClass * if so, return attributes which the class requires/allows * else if requested description is !objectClass, return * attributes which the class does not require/allow */ if ( !( attrs->an_flags & SLAP_AN_OCINITED )) { if( attrs->an_name.bv_val ) { switch( attrs->an_name.bv_val[0] ) { case '@': /* @objectClass */ case '+': /* +objectClass (deprecated) */ case '!': { /* exclude */ struct berval ocname; ocname.bv_len = attrs->an_name.bv_len - 1; ocname.bv_val = &attrs->an_name.bv_val[1]; oc = oc_bvfind( &ocname ); if ( oc && attrs->an_name.bv_val[0] == '!' ) { attrs->an_flags |= SLAP_AN_OCEXCLUDE; } else { attrs->an_flags &= ~SLAP_AN_OCEXCLUDE; } } break; default: /* old (deprecated) way */ oc = oc_bvfind( &attrs->an_name ); } attrs->an_oc = oc; } attrs->an_flags |= SLAP_AN_OCINITED; } oc = attrs->an_oc; if( oc != NULL ) { if ( attrs->an_flags & SLAP_AN_OCEXCLUDE ) { if ( oc == slap_schema.si_oc_extensibleObject ) { /* extensibleObject allows the return of anything */ return 0; } if( oc->soc_required ) { /* allow return of required attributes */ int i; for ( i = 0; oc->soc_required[i] != NULL; i++ ) { for (a = desc->ad_type; a; a=a->sat_sup) { if ( a == oc->soc_required[i] ) { return 0; } } } } if( oc->soc_allowed ) { /* allow return of allowed attributes */ int i; for ( i = 0; oc->soc_allowed[i] != NULL; i++ ) { for (a = desc->ad_type; a; a=a->sat_sup) { if ( a == oc->soc_allowed[i] ) { return 0; } } } } return 1; } if ( oc == slap_schema.si_oc_extensibleObject ) { /* extensibleObject allows the return of anything */ return 1; } if( oc->soc_required ) { /* allow return of required attributes */ int i; for ( i = 0; oc->soc_required[i] != NULL; i++ ) { for (a = desc->ad_type; a; a=a->sat_sup) { if ( a == oc->soc_required[i] ) { return 1; } } } } if( oc->soc_allowed ) { /* allow return of allowed attributes */ int i; for ( i = 0; oc->soc_allowed[i] != NULL; i++ ) { for (a = desc->ad_type; a; a=a->sat_sup) { if ( a == oc->soc_allowed[i] ) { return 1; } } } } } else { const char *text; /* give it a chance of being retrieved by a proxy... */ (void)slap_bv2undef_ad( &attrs->an_name, &attrs->an_desc, &text, SLAP_AD_PROXIED|SLAP_AD_NOINSERT ); } } return 0; }
static int gssattr_dynacl_mask( void *priv, Operation *op, Entry *target, AttributeDescription *desc, struct berval *val, int nmatch, regmatch_t *matches, slap_access_t *grant, slap_access_t *deny ) { gssattr_t *gssattr = (gssattr_t *)priv; sasl_conn_t *sasl_ctx = op->o_conn->c_sasl_authctx; gss_name_t gss_name = GSS_C_NO_NAME; OM_uint32 major, minor; int more = -1; int authenticated, complete; gss_buffer_desc attr = GSS_C_EMPTY_BUFFER; int granted = 0; ACL_INVALIDATE( *deny ); if ( sasl_ctx == NULL || sasl_getprop( sasl_ctx, SASL_GSS_PEER_NAME, (const void **)&gss_name) != 0 || gss_name == GSS_C_NO_NAME ) { return 0; } attr.length = gssattr->gssattr_name.bv_len; attr.value = gssattr->gssattr_name.bv_val; while ( more != 0 ) { AclRegexMatches amatches = { 0 }; gss_buffer_desc gss_value = GSS_C_EMPTY_BUFFER; gss_buffer_desc gss_display_value = GSS_C_EMPTY_BUFFER; struct berval bv_value; major = gss_get_name_attribute( &minor, gss_name, &attr, &authenticated, &complete, &gss_value, &gss_display_value, &more ); if ( GSS_ERROR( major ) ) { break; } else if ( authenticated == 0 ) { gss_release_buffer( &minor, &gss_value ); gss_release_buffer( &minor, &gss_display_value ); continue; } bv_value.bv_len = gss_value.length; bv_value.bv_val = (char *)gss_value.value; if ( !ber_bvccmp( &gssattr->gssattr_value, '*' ) ) { if ( gssattr->gssattr_style != ACL_STYLE_BASE ) { amatches.dn_count = nmatch; AC_MEMCPY( amatches.dn_data, matches, sizeof( amatches.dn_data ) ); } switch ( gssattr->gssattr_style ) { case ACL_STYLE_REGEX: /* XXX assumes value NUL terminated */ granted = regex_matches( &gssattr->gssattr_value, bv_value.bv_val, &target->e_nname, val, &amatches ); break; case ACL_STYLE_EXPAND: { struct berval bv; char buf[ACL_BUF_SIZE]; bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; granted = ( acl_string_expand( &bv, &gssattr->gssattr_value, &target->e_nname, val, &amatches ) == 0 ) && ( ber_bvstrcmp( &bv, &bv_value) == 0 ); break; } case ACL_STYLE_BASE: granted = ( ber_bvstrcmp( &gssattr->gssattr_value, &bv_value ) == 0 ); break; default: assert(0); break; } } else { granted = 1; } gss_release_buffer( &minor, &gss_value ); gss_release_buffer( &minor, &gss_display_value ); if ( granted ) { break; } } if ( granted ) { ACL_LVL_ASSIGN_WRITE( *grant ); } return 0; }