diff --git a/pkg/services/object/put/service.go b/pkg/services/object/put/service.go index f26044d4d..93aff63b8 100644 --- a/pkg/services/object/put/service.go +++ b/pkg/services/object/put/service.go @@ -6,6 +6,7 @@ import ( "github.com/nspcc-dev/neofs-node/pkg/core/container" "github.com/nspcc-dev/neofs-node/pkg/core/netmap" + "github.com/nspcc-dev/neofs-node/pkg/core/object" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/localstore" "github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-node/pkg/services/session/storage" @@ -38,11 +39,14 @@ type cfg struct { workerPool util.WorkerPool localAddrSrc network.LocalAddressSource + + fmtValidator *object.FormatValidator } func defaultCfg() *cfg { return &cfg{ - workerPool: new(util.SyncWorkerPool), + workerPool: new(util.SyncWorkerPool), + fmtValidator: object.NewFormatValidator(), } } diff --git a/pkg/services/object/put/streamer.go b/pkg/services/object/put/streamer.go index 838bbe7ff..7fbfda060 100644 --- a/pkg/services/object/put/streamer.go +++ b/pkg/services/object/put/streamer.go @@ -50,7 +50,10 @@ func (p *Streamer) initTarget(prm *PutInitPrm) error { if prm.token == nil { // prepare untrusted-Put object target - p.target = p.newCommonTarget(prm) + p.target = &validatingTarget{ + nextTarget: p.newCommonTarget(prm), + fmt: p.fmtValidator, + } return nil } diff --git a/pkg/services/object/put/validation.go b/pkg/services/object/put/validation.go new file mode 100644 index 000000000..a384822a9 --- /dev/null +++ b/pkg/services/object/put/validation.go @@ -0,0 +1,57 @@ +package putsvc + +import ( + "bytes" + "crypto/sha256" + "hash" + + "github.com/nspcc-dev/neofs-api-go/pkg" + "github.com/nspcc-dev/neofs-node/pkg/core/object" + "github.com/nspcc-dev/neofs-node/pkg/services/object_manager/transformer" + "github.com/nspcc-dev/tzhash/tz" + "github.com/pkg/errors" +) + +type validatingTarget struct { + nextTarget transformer.ObjectTarget + + fmt *object.FormatValidator + + hash hash.Hash + + checksum []byte +} + +func (t *validatingTarget) WriteHeader(obj *object.RawObject) error { + cs := obj.GetPayloadChecksum() + switch typ := cs.GetType(); typ { + default: + return errors.Errorf("(%T) unsupported payload checksum type %v", t, typ) + case pkg.ChecksumSHA256: + t.hash = sha256.New() + case pkg.ChecksumTZ: + t.hash = tz.New() + } + + t.checksum = cs.GetSum() + + if err := t.fmt.Validate(obj.Object()); err != nil { + return errors.Wrapf(err, "(%T) coult not validate object format", t) + } + + return t.nextTarget.WriteHeader(obj) +} + +func (t *validatingTarget) Write(p []byte) (n int, err error) { + t.hash.Write(p) + + return t.nextTarget.Write(p) +} + +func (t *validatingTarget) Close() (*transformer.AccessIdentifiers, error) { + if !bytes.Equal(t.hash.Sum(nil), t.checksum) { + return nil, errors.Errorf("(%T) incorrect payload checksum", t) + } + + return t.nextTarget.Close() +}