package acl import ( "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" ) // wrapper around basic ACL to provide easy access to basic ACL fields type basicACLHelper uint32 const ( reservedBitNumber = 2 // first left bits are reserved stickyBitPos = reservedBitNumber // X-bit after reserved bits finalBitPos = stickyBitPos + 1 // F-bit after X-bit ) const ( opOffset = finalBitPos + 1 // offset of operation bits bitsPerOp = 4 // number of bits per operation opNumber = 7 // number of operation bit sections ) const ( bitUser uint8 = iota bitSystem bitOthers bitBearer ) const leftACLBitPos = opOffset + bitsPerOp*opNumber - 1 var ( order = map[eacl.Operation]uint8{ eacl.OperationRangeHash: 0, eacl.OperationRange: 1, eacl.OperationSearch: 2, eacl.OperationDelete: 3, eacl.OperationPut: 4, eacl.OperationHead: 5, eacl.OperationGet: 6, } ) // returns true if n-th left bit is set (starting at 0). func isLeftBitSet(value basicACLHelper, n uint8) bool { bitMask := basicACLHelper(1 << (leftACLBitPos - n)) return bitMask != 0 && value&bitMask == bitMask } // sets n-th left bit (starting at 0). func setLeftBit(value *basicACLHelper, n uint8) { *value |= basicACLHelper(1 << (leftACLBitPos - n)) } // resets n-th left bit (starting at 0). func resetLeftBit(value *basicACLHelper, n uint8) { *value &= ^basicACLHelper(1 << (leftACLBitPos - n)) } // Final returns true if final option is enabled in ACL. func (a basicACLHelper) Final() bool { return isLeftBitSet(a, finalBitPos) } // SetFinal enables final option in ACL. func (a *basicACLHelper) SetFinal() { setLeftBit(a, finalBitPos) } // ResetFinal disables final option in ACL. func (a *basicACLHelper) ResetFinal() { resetLeftBit(a, finalBitPos) } // Sticky returns true if sticky option is enabled in ACL. func (a basicACLHelper) Sticky() bool { return isLeftBitSet(a, stickyBitPos) } // SetSticky enables the sticky option in ACL. func (a *basicACLHelper) SetSticky() { setLeftBit(a, stickyBitPos) } // ResetSticky disables the sticky option in ACL. func (a *basicACLHelper) ResetSticky() { resetLeftBit(a, stickyBitPos) } // UserAllowed returns true if user allowed the n-th operation in ACL. func (a basicACLHelper) UserAllowed(op eacl.Operation) bool { if n, ok := order[op]; ok { return isLeftBitSet(a, opOffset+n*bitsPerOp+bitUser) } return false } // AllowUser allows user the n-th operation in ACL. func (a *basicACLHelper) AllowUser(op eacl.Operation) { if n, ok := order[op]; ok { setLeftBit(a, opOffset+n*bitsPerOp+bitUser) } } // ForbidUser forbids user the n-th operation in ACL. func (a *basicACLHelper) ForbidUser(op eacl.Operation) { if n, ok := order[op]; ok { resetLeftBit(a, opOffset+n*bitsPerOp+bitUser) } } // SystemAllowed returns true if System group allowed the n-th operation is set in ACL. func (a basicACLHelper) SystemAllowed(op eacl.Operation) bool { if op != eacl.OperationDelete && op != eacl.OperationRange { return true } if n, ok := order[op]; ok { return isLeftBitSet(a, opOffset+n*bitsPerOp+bitSystem) } return false } // InnerRingAllowed returns true if the operation is allowed by ACL for // InnerRing nodes, as part of System group. func (a basicACLHelper) InnerRingAllowed(op eacl.Operation) bool { switch op { case eacl.OperationSearch, eacl.OperationRangeHash, eacl.OperationHead, eacl.OperationGet: return true default: if n, ok := order[op]; ok { return isLeftBitSet(a, opOffset+n*bitsPerOp+bitSystem) } return false } } // AllowSystem allows System group the n-th operation in ACL. func (a *basicACLHelper) AllowSystem(op eacl.Operation) { if n, ok := order[op]; ok { setLeftBit(a, opOffset+n*bitsPerOp+bitSystem) } } // ForbidSystem forbids System group the n-th operation in ACL. func (a *basicACLHelper) ForbidSystem(op eacl.Operation) { if n, ok := order[op]; ok { resetLeftBit(a, opOffset+n*bitsPerOp+bitSystem) } } // OthersAllowed returns true if Others group allowed the n-th operation is set in ACL. func (a basicACLHelper) OthersAllowed(op eacl.Operation) bool { if n, ok := order[op]; ok { return isLeftBitSet(a, opOffset+n*bitsPerOp+bitOthers) } return false } // AllowOthers allows Others group the n-th operation in ACL. func (a *basicACLHelper) AllowOthers(op eacl.Operation) { if n, ok := order[op]; ok { setLeftBit(a, opOffset+n*bitsPerOp+bitOthers) } } // ForbidOthers forbids Others group the n-th operation in ACL. func (a *basicACLHelper) ForbidOthers(op eacl.Operation) { if n, ok := order[op]; ok { resetLeftBit(a, opOffset+n*bitsPerOp+bitOthers) } } // BearerAllowed returns true if Bearer token usage is allowed for n-th operation in ACL. func (a basicACLHelper) BearerAllowed(op eacl.Operation) bool { if n, ok := order[op]; ok { return isLeftBitSet(a, opOffset+n*bitsPerOp+bitBearer) } return false } // AllowBearer allows Bearer token usage for n-th operation in ACL. func (a *basicACLHelper) AllowBearer(op eacl.Operation) { if n, ok := order[op]; ok { setLeftBit(a, opOffset+n*bitsPerOp+bitBearer) } } // ForbidBearer forbids Bearer token usage for n-th operation in ACL. func (a *basicACLHelper) ForbidBearer(op eacl.Operation) { if n, ok := order[op]; ok { resetLeftBit(a, opOffset+n*bitsPerOp+bitBearer) } }