mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-29 09:34:03 +08:00
Enforce Cid security rules for getting and adding blocks
License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>
This commit is contained in:
@ -10,6 +10,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
exchange "github.com/ipfs/go-ipfs/exchange"
|
exchange "github.com/ipfs/go-ipfs/exchange"
|
||||||
|
"github.com/ipfs/go-ipfs/removeme/verifcid"
|
||||||
|
|
||||||
logging "gx/ipfs/QmRb5jh8z2E8hMGN2tkvs1yHynUanqnZ3UeKwgN1i9P1F8/go-log"
|
logging "gx/ipfs/QmRb5jh8z2E8hMGN2tkvs1yHynUanqnZ3UeKwgN1i9P1F8/go-log"
|
||||||
blockstore "gx/ipfs/QmTVDM4LCSUMFNQzbDLL9zQwp8usE6QHymFdh3h8vL9v6b/go-ipfs-blockstore"
|
blockstore "gx/ipfs/QmTVDM4LCSUMFNQzbDLL9zQwp8usE6QHymFdh3h8vL9v6b/go-ipfs-blockstore"
|
||||||
@ -130,6 +131,11 @@ func NewSession(ctx context.Context, bs BlockService) *Session {
|
|||||||
// TODO pass a context into this if the remote.HasBlock is going to remain here.
|
// TODO pass a context into this if the remote.HasBlock is going to remain here.
|
||||||
func (s *blockService) AddBlock(o blocks.Block) error {
|
func (s *blockService) AddBlock(o blocks.Block) error {
|
||||||
c := o.Cid()
|
c := o.Cid()
|
||||||
|
// hash security
|
||||||
|
err := verifcid.ValidateCid(c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if s.checkFirst {
|
if s.checkFirst {
|
||||||
if has, err := s.blockstore.Has(c); has || err != nil {
|
if has, err := s.blockstore.Has(c); has || err != nil {
|
||||||
return err
|
return err
|
||||||
@ -149,6 +155,13 @@ func (s *blockService) AddBlock(o blocks.Block) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *blockService) AddBlocks(bs []blocks.Block) error {
|
func (s *blockService) AddBlocks(bs []blocks.Block) error {
|
||||||
|
//hash security
|
||||||
|
for _, b := range bs {
|
||||||
|
err := verifcid.ValidateCid(b.Cid())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
var toput []blocks.Block
|
var toput []blocks.Block
|
||||||
if s.checkFirst {
|
if s.checkFirst {
|
||||||
toput = make([]blocks.Block, 0, len(bs))
|
toput = make([]blocks.Block, 0, len(bs))
|
||||||
@ -189,10 +202,15 @@ func (s *blockService) GetBlock(ctx context.Context, c *cid.Cid) (blocks.Block,
|
|||||||
f = s.exchange
|
f = s.exchange
|
||||||
}
|
}
|
||||||
|
|
||||||
return getBlock(ctx, c, s.blockstore, f)
|
return getBlock(ctx, c, s.blockstore, f) //hash security
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBlock(ctx context.Context, c *cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) (blocks.Block, error) {
|
func getBlock(ctx context.Context, c *cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) (blocks.Block, error) {
|
||||||
|
err := verifcid.ValidateCid(c)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
block, err := bs.Get(c)
|
block, err := bs.Get(c)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return block, nil
|
return block, nil
|
||||||
@ -224,11 +242,18 @@ func getBlock(ctx context.Context, c *cid.Cid, bs blockstore.Blockstore, f excha
|
|||||||
// the returned channel.
|
// the returned channel.
|
||||||
// NB: No guarantees are made about order.
|
// NB: No guarantees are made about order.
|
||||||
func (s *blockService) GetBlocks(ctx context.Context, ks []*cid.Cid) <-chan blocks.Block {
|
func (s *blockService) GetBlocks(ctx context.Context, ks []*cid.Cid) <-chan blocks.Block {
|
||||||
return getBlocks(ctx, ks, s.blockstore, s.exchange)
|
return getBlocks(ctx, ks, s.blockstore, s.exchange) //hash security
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBlocks(ctx context.Context, ks []*cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) <-chan blocks.Block {
|
func getBlocks(ctx context.Context, ks []*cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) <-chan blocks.Block {
|
||||||
out := make(chan blocks.Block)
|
out := make(chan blocks.Block)
|
||||||
|
for _, c := range ks {
|
||||||
|
// hash security
|
||||||
|
if err := verifcid.ValidateCid(c); err != nil {
|
||||||
|
log.Errorf("unsafe CID (%s) passed to blockService.GetBlocks: %s", c, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(out)
|
defer close(out)
|
||||||
var misses []*cid.Cid
|
var misses []*cid.Cid
|
||||||
@ -285,12 +310,12 @@ type Session struct {
|
|||||||
|
|
||||||
// GetBlock gets a block in the context of a request session
|
// GetBlock gets a block in the context of a request session
|
||||||
func (s *Session) GetBlock(ctx context.Context, c *cid.Cid) (blocks.Block, error) {
|
func (s *Session) GetBlock(ctx context.Context, c *cid.Cid) (blocks.Block, error) {
|
||||||
return getBlock(ctx, c, s.bs, s.ses)
|
return getBlock(ctx, c, s.bs, s.ses) // hash security
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlocks gets blocks in the context of a request session
|
// GetBlocks gets blocks in the context of a request session
|
||||||
func (s *Session) GetBlocks(ctx context.Context, ks []*cid.Cid) <-chan blocks.Block {
|
func (s *Session) GetBlocks(ctx context.Context, ks []*cid.Cid) <-chan blocks.Block {
|
||||||
return getBlocks(ctx, ks, s.bs, s.ses)
|
return getBlocks(ctx, ks, s.bs, s.ses) // hash security
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ BlockGetter = (*Session)(nil)
|
var _ BlockGetter = (*Session)(nil)
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
dag "github.com/ipfs/go-ipfs/merkledag"
|
dag "github.com/ipfs/go-ipfs/merkledag"
|
||||||
resolver "github.com/ipfs/go-ipfs/path/resolver"
|
resolver "github.com/ipfs/go-ipfs/path/resolver"
|
||||||
pin "github.com/ipfs/go-ipfs/pin"
|
pin "github.com/ipfs/go-ipfs/pin"
|
||||||
|
"github.com/ipfs/go-ipfs/removeme/verifbs"
|
||||||
repo "github.com/ipfs/go-ipfs/repo"
|
repo "github.com/ipfs/go-ipfs/repo"
|
||||||
cfg "github.com/ipfs/go-ipfs/repo/config"
|
cfg "github.com/ipfs/go-ipfs/repo/config"
|
||||||
uio "github.com/ipfs/go-ipfs/unixfs/io"
|
uio "github.com/ipfs/go-ipfs/unixfs/io"
|
||||||
@ -170,7 +171,9 @@ func setupNode(ctx context.Context, n *IpfsNode, cfg *BuildCfg) error {
|
|||||||
TempErrFunc: isTooManyFDError,
|
TempErrFunc: isTooManyFDError,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//hash security
|
||||||
bs := bstore.NewBlockstore(rds)
|
bs := bstore.NewBlockstore(rds)
|
||||||
|
bs = &verifbs.VerifBS{bs}
|
||||||
|
|
||||||
opts := bstore.DefaultCacheOpts()
|
opts := bstore.DefaultCacheOpts()
|
||||||
conf, err := n.Repo.Config()
|
conf, err := n.Repo.Config()
|
||||||
@ -196,8 +199,10 @@ func setupNode(ctx context.Context, n *IpfsNode, cfg *BuildCfg) error {
|
|||||||
n.Blockstore = bstore.NewGCBlockstore(cbs, n.GCLocker)
|
n.Blockstore = bstore.NewGCBlockstore(cbs, n.GCLocker)
|
||||||
|
|
||||||
if conf.Experimental.FilestoreEnabled {
|
if conf.Experimental.FilestoreEnabled {
|
||||||
|
// hash security
|
||||||
n.Filestore = filestore.NewFilestore(bs, n.Repo.FileManager())
|
n.Filestore = filestore.NewFilestore(bs, n.Repo.FileManager())
|
||||||
n.Blockstore = bstore.NewGCBlockstore(n.Filestore, n.GCLocker)
|
n.Blockstore = bstore.NewGCBlockstore(n.Filestore, n.GCLocker)
|
||||||
|
n.Blockstore = &verifbs.VerifBSGC{n.Blockstore}
|
||||||
}
|
}
|
||||||
|
|
||||||
rcfg, err := n.Repo.Config()
|
rcfg, err := n.Repo.Config()
|
||||||
|
@ -258,7 +258,7 @@ You can now check what blocks have been created by:
|
|||||||
exch = offline.Exchange(addblockstore)
|
exch = offline.Exchange(addblockstore)
|
||||||
}
|
}
|
||||||
|
|
||||||
bserv := blockservice.New(addblockstore, exch)
|
bserv := blockservice.New(addblockstore, exch) //hash security 001
|
||||||
dserv := dag.NewDAGService(bserv)
|
dserv := dag.NewDAGService(bserv)
|
||||||
|
|
||||||
outChan := make(chan interface{}, adderOutChanSize)
|
outChan := make(chan interface{}, adderOutChanSize)
|
||||||
|
63
removeme/verifbs/verifbs.go
Normal file
63
removeme/verifbs/verifbs.go
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package verifbs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ipfs/go-ipfs/removeme/verifcid"
|
||||||
|
|
||||||
|
bstore "gx/ipfs/QmTVDM4LCSUMFNQzbDLL9zQwp8usE6QHymFdh3h8vL9v6b/go-ipfs-blockstore"
|
||||||
|
cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
|
||||||
|
blocks "gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format"
|
||||||
|
)
|
||||||
|
|
||||||
|
type VerifBSGC struct {
|
||||||
|
bstore.GCBlockstore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *VerifBSGC) Put(b blocks.Block) error {
|
||||||
|
if err := verifcid.ValidateCid(b.Cid()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bs.GCBlockstore.Put(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *VerifBSGC) PutMany(blks []blocks.Block) error {
|
||||||
|
for _, b := range blks {
|
||||||
|
if err := verifcid.ValidateCid(b.Cid()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bs.GCBlockstore.PutMany(blks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *VerifBSGC) Get(c *cid.Cid) (blocks.Block, error) {
|
||||||
|
if err := verifcid.ValidateCid(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bs.GCBlockstore.Get(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
type VerifBS struct {
|
||||||
|
bstore.Blockstore
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *VerifBS) Put(b blocks.Block) error {
|
||||||
|
if err := verifcid.ValidateCid(b.Cid()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return bs.Blockstore.Put(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *VerifBS) PutMany(blks []blocks.Block) error {
|
||||||
|
for _, b := range blks {
|
||||||
|
if err := verifcid.ValidateCid(b.Cid()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bs.Blockstore.PutMany(blks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bs *VerifBS) Get(c *cid.Cid) (blocks.Block, error) {
|
||||||
|
if err := verifcid.ValidateCid(c); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return bs.Blockstore.Get(c)
|
||||||
|
}
|
@ -185,11 +185,11 @@ test_expect_success "block get output looks right" '
|
|||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "can set multihash type and length on block put" '
|
test_expect_success "can set multihash type and length on block put" '
|
||||||
HASH=$(echo "foooo" | ipfs block put --format=raw --mhtype=sha3 --mhlen=16)
|
HASH=$(echo "foooo" | ipfs block put --format=raw --mhtype=sha3 --mhlen=20)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "output looks good" '
|
test_expect_success "output looks good" '
|
||||||
test "z25ScPysKoxJBcPxczn9NvuHiZU5" = "$HASH"
|
test "z83bYcqyBkbx5fuNAcvbdv4pr5RYQiEpK" = "$HASH"
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "can read block with different hash" '
|
test_expect_success "can read block with different hash" '
|
||||||
|
Reference in New Issue
Block a user