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 idattr_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 ) { idattr_t *id = (idattr_t *)priv; Entry *user = NULL; int rc = LDAP_INSUFFICIENT_ACCESS; int user_rc = LDAP_INSUFFICIENT_ACCESS; int target_rc = LDAP_INSUFFICIENT_ACCESS; Backend *be = op->o_bd, *group_be = NULL, *user_be = NULL; AttributeDescription *searchAttr = NULL; ObjectClass *searchObject = NULL; struct berval *searchTarget = NULL; Entry *searchEntry = NULL; ACL_INVALIDATE( *deny ); Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: pat(%s) type(%d) op(%d)\n", id->idattr_pat.bv_val, id->idattr_type, id->idattr_ops ); Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: target(%s) op->o_ndn(%s)\n", target->e_nname.bv_val, op->o_ndn.bv_val, 0 ); if (id->idattr_ops && (id->idattr_ops != op->o_tag)) { Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: Operation Not Allowed - Ops allowed (%d), Requested Op (%d)\n", id->idattr_ops, op->o_tag, 0 ); // LDAP_INSUFFICIENT_ACCESS return 0; } if (!op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { user_be = op->o_bd = select_backend( &op->o_ndn, 0); if ( op->o_bd == NULL ) { Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: op->o_bd == NULL \n", 0, 0, 0 ); op->o_bd = be; return 0; } } // check ACL TYPE Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: idattr_type(%d)\n", id->idattr_type, 0, 0 ); if (id->idattr_type == UUID_TYPE || id->idattr_type == OWNER_TYPE) { searchAttr = idattr_uuid; searchObject = idattr_extensible_object; searchTarget = &op->o_ndn; } else if (id->idattr_type == SID_TYPE) { searchAttr = idattr_sid; searchObject = idattr_extensible_object; searchTarget = &op->o_conn->c_authz.sai_ndn; } else if (id->idattr_type == SELFWRITE_TYPE) { searchAttr = id->idattr_selfattrDesc; searchObject = idattr_extensible_object; searchTarget = &op->o_ndn; } else if (id->idattr_type == USERS_TYPE) { if (BER_BVISEMPTY( &op->o_ndn )) { // LDAP_INSUFFICIENT_ACCESS op->o_bd = be; return 0; } else { // check for APPLYTO clause if (id->idattr_applyto) { rc = idattr_check_applyto(op, target, searchAttr, id); } else { rc = LDAP_SUCCESS; } goto assignaccess; } } else { Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: unknown idattr_type(%s)\n", id->idattr_type, 0, 0 ); // LDAP_INSUFFICIENT_ACCESS return 0; } if (op->o_conn->c_authz.c_sai_krb5_auth_data_provisioned) { user_rc = LDAP_SUCCESS; } else if (searchAttr) { // lookup user record user_rc = be_entry_get_rw( op, searchTarget, NULL, searchAttr, 0, &user ); Debug( LDAP_DEBUG_ACL, "idattr_dynacl_mask: be_entry_get_rw user_rc(%d) user(%x) \n", user_rc, user, 0 ); if ( user_rc != LDAP_SUCCESS || user == NULL ) { op->o_bd = be; return 0; } } if ( user_rc == LDAP_SUCCESS || user != NULL ) { user_rc = idattr_check_isuser(op, user, searchAttr, id); if (user_rc == LDAP_SUCCESS) { switch ( id->idattr_type ) { case SELFWRITE_TYPE: user_rc = idattr_check_selfwrite(op, target, user, val, id); break; case OWNER_TYPE: user_rc = idattr_check_isowner(op, user, target, searchAttr, id); break; case UUID_TYPE: case SID_TYPE: user_rc = LDAP_SUCCESS; break; default: break; } if (user_rc == LDAP_SUCCESS) { if (id->idattr_applyto) { rc = idattr_check_applyto(op, target, searchAttr, id); } else { rc = LDAP_SUCCESS; } } } } else { rc = LDAP_NO_SUCH_OBJECT; } assignaccess: if ( rc == LDAP_SUCCESS ) { ACL_LVL_ASSIGN_WRITE( *grant ); } cleanup: if ( user != NULL) { op->o_bd = user_be; be_entry_release_r( op, user ); op->o_bd = be; } 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; }