diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index 08aa226f..63485a70 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -51,20 +51,10 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op if err != nil { return err } - if op == acl.OpObjectGet { - // verify if the request for a client operation - // was signed by a key from authorized list. - // Operation must be one of READ. - sign := req.GetSignature() - if sign == nil { - return errors.New("missing signature") - } - var key = sign.GetKey() - for i := range s.authorizedKeys { - if bytes.Equal(s.authorizedKeys[i], key) { - return nil - } - } + + isAuthorized, err := s.isAuthorized(req, op) + if isAuthorized || err != nil { + return err } cnr, err := s.cnrSource.Get(cid) @@ -74,18 +64,9 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op eaclOp := eACLOp(op) - var bt *bearer.Token - if len(rawBearer) > 0 { - bt = new(bearer.Token) - if err = bt.Unmarshal(rawBearer); err != nil { - return eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err)) - } - if !bt.AssertContainer(cid) { - return eACLErr(eaclOp, errBearerWrongContainer) - } - if !bt.VerifySignature() { - return eACLErr(eaclOp, errBearerSignature) - } + bt, err := parseBearer(rawBearer, cid, eaclOp) + if err != nil { + return err } role, err := roleFromReq(cnr, req, bt) @@ -117,32 +98,65 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op var tb eacl.Table signer := req.GetSignature().GetKey() - if tableFromBearer { - if bt.Impersonate() { - tbCore, err := s.eaclSource.GetEACL(cid) - if err != nil { - return handleGetEACLError(err) - } - tb = *tbCore.Value - signer = bt.SigningKeyBytes() - } else { - if !bearer.ResolveIssuer(*bt).Equals(cnr.Value.Owner()) { - return eACLErr(eaclOp, errBearerWrongOwner) - } - tb = bt.EACLTable() + if tableFromBearer && !bt.Impersonate() { + if !bearer.ResolveIssuer(*bt).Equals(cnr.Value.Owner()) { + return eACLErr(eaclOp, errBearerWrongOwner) } + tb = bt.EACLTable() } else { tbCore, err := s.eaclSource.GetEACL(cid) if err != nil { return handleGetEACLError(err) } - tb = *tbCore.Value + + if bt.Impersonate() { + signer = bt.SigningKeyBytes() + } } return checkEACL(tb, signer, eACLRole(role), eaclOp) } +// Returns true iff the operation is read-only and request was signed +// with one of the authorized keys. +func (s *Service) isAuthorized(req message, op acl.Op) (bool, error) { + if op != acl.OpObjectGet { + return false, nil + } + + sign := req.GetSignature() + if sign == nil { + return false, errors.New("missing signature") + } + + key := sign.GetKey() + for i := range s.authorizedKeys { + if bytes.Equal(s.authorizedKeys[i], key) { + return true, nil + } + } + return false, nil +} + +func parseBearer(rawBearer []byte, cid cidSDK.ID, eaclOp eacl.Operation) (*bearer.Token, error) { + if len(rawBearer) == 0 { + return nil, nil + } + + bt := new(bearer.Token) + if err := bt.Unmarshal(rawBearer); err != nil { + return nil, eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err)) + } + if !bt.AssertContainer(cid) { + return nil, eACLErr(eaclOp, errBearerWrongContainer) + } + if !bt.VerifySignature() { + return nil, eACLErr(eaclOp, errBearerSignature) + } + return bt, nil +} + func handleGetEACLError(err error) error { if client.IsErrEACLNotFound(err) { return nil