static int regex_matches( struct berval *pat, /* pattern to expand and match against */ char *str, /* string to match against pattern */ struct berval *dn_matches, /* buffer with $N expansion variables from DN */ struct berval *val_matches, /* buffer with $N expansion variables from val */ AclRegexMatches *matches /* offsets in buffer for $N expansion variables */ ) { regex_t re; char newbuf[ACL_BUF_SIZE]; struct berval bv; int rc; bv.bv_len = sizeof( newbuf ) - 1; bv.bv_val = newbuf; if (str == NULL) { str = ""; }; acl_string_expand( &bv, pat, dn_matches, val_matches, matches ); rc = regcomp( &re, newbuf, REG_EXTENDED|REG_ICASE ); if ( rc ) { char error[ACL_BUF_SIZE]; regerror( rc, &re, error, sizeof( error ) ); Debug( LDAP_DEBUG_TRACE, "compile( \"%s\", \"%s\") failed %s\n", pat->bv_val, str, error ); return( 0 ); } rc = regexec( &re, str, 0, NULL, 0 ); regfree( &re ); Debug( LDAP_DEBUG_TRACE, "=> regex_matches: string: %s\n", str, 0, 0 ); Debug( LDAP_DEBUG_TRACE, "=> regex_matches: rc: %d %s\n", rc, !rc ? "matches" : "no matches", 0 ); return( !rc ); }
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 pg_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 ) { pg_t *pg = (pg_t *)priv; Entry *group = NULL, *user = NULL; int rc; Backend *be = op->o_bd, *group_be = NULL, *user_be = NULL; struct berval group_ndn; ACL_INVALIDATE( *deny ); /* get user */ if ( target && dn_match( &target->e_nname, &op->o_ndn ) ) { user = target; rc = LDAP_SUCCESS; } else { user_be = op->o_bd = select_backend( &op->o_ndn, 0 ); if ( op->o_bd == NULL ) { op->o_bd = be; return 0; } rc = be_entry_get_rw( op, &op->o_ndn, pg_posixAccount, pg_uidNumber, 0, &user ); } if ( rc != LDAP_SUCCESS || user == NULL ) { op->o_bd = be; return 0; } /* get target */ if ( pg->pg_style == ACL_STYLE_EXPAND ) { char buf[ 1024 ]; struct berval bv; AclRegexMatches amatches = { 0 }; amatches.dn_count = nmatch; AC_MEMCPY( amatches.dn_data, matches, sizeof( amatches.dn_data ) ); bv.bv_len = sizeof( buf ) - 1; bv.bv_val = buf; if ( acl_string_expand( &bv, &pg->pg_pat, &target->e_nname, NULL, &amatches ) ) { goto cleanup; } if ( dnNormalize( 0, NULL, NULL, &bv, &group_ndn, op->o_tmpmemctx ) != LDAP_SUCCESS ) { /* did not expand to a valid dn */ goto cleanup; } } else { group_ndn = pg->pg_pat; } if ( target && dn_match( &target->e_nname, &group_ndn ) ) { group = target; rc = LDAP_SUCCESS; } else { group_be = op->o_bd = select_backend( &group_ndn, 0 ); if ( op->o_bd == NULL ) { goto cleanup; } rc = be_entry_get_rw( op, &group_ndn, pg_posixGroup, pg_memberUid, 0, &group ); } if ( group_ndn.bv_val != pg->pg_pat.bv_val ) { op->o_tmpfree( group_ndn.bv_val, op->o_tmpmemctx ); } if ( rc == LDAP_SUCCESS && group != NULL ) { Attribute *a_uid, *a_member; a_uid = attr_find( user->e_attrs, pg_uidNumber ); if ( !a_uid || !BER_BVISNULL( &a_uid->a_nvals[ 1 ] ) ) { rc = LDAP_NO_SUCH_ATTRIBUTE; } else { a_member = attr_find( group->e_attrs, pg_memberUid ); if ( !a_member ) { rc = LDAP_NO_SUCH_ATTRIBUTE; } else { rc = value_find_ex( pg_memberUid, SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH, a_member->a_nvals, &a_uid->a_nvals[ 0 ], op->o_tmpmemctx ); } } } else { rc = LDAP_NO_SUCH_OBJECT; } if ( rc == LDAP_SUCCESS ) { ACL_LVL_ASSIGN_WRITE( *grant ); } cleanup:; if ( group != NULL && group != target ) { op->o_bd = group_be; be_entry_release_r( op, group ); op->o_bd = be; } if ( user != NULL && user != target ) { op->o_bd = user_be; be_entry_release_r( op, user ); op->o_bd = be; } 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; }