@cryptotaxi247 / kubo / commits / c30422d79

Enforce Cid security rules for getting and adding blocks

License: MIT Signed-off-by: Jakub Sztandera <kubuxu@protonmail.ch>

Jakub Sztandera committed Mar 1, 2018 at 21:21 UTC c30422d790149fa648a32c052fdfab5fc7438bd8
5 files changed +100 -7
blockservice/blockservice.go
+29 -4
@@ -10,6 +10,7 @@ import (
10 "io"
11
12 exchange "github.com/ipfs/go-ipfs/exchange"
13 + "github.com/ipfs/go-ipfs/removeme/verifcid"
14
15 logging "gx/ipfs/QmRb5jh8z2E8hMGN2tkvs1yHynUanqnZ3UeKwgN1i9P1F8/go-log"
16 blockstore "gx/ipfs/QmTVDM4LCSUMFNQzbDLL9zQwp8usE6QHymFdh3h8vL9v6b/go-ipfs-blockstore"
@@ -130,6 +131,11 @@ func NewSession(ctx context.Context, bs BlockService) *Session {
131 // TODO pass a context into this if the remote.HasBlock is going to remain here.
132 func (s *blockService) AddBlock(o blocks.Block) error {
133 c := o.Cid()
134 + // hash security
135 + err := verifcid.ValidateCid(c)
136 + if err != nil {
137 + return err
138 + }
139 if s.checkFirst {
140 if has, err := s.blockstore.Has(c); has || err != nil {
141 return err
@@ -149,6 +155,13 @@ func (s *blockService) AddBlock(o blocks.Block) error {
155 }
156
157 func (s *blockService) AddBlocks(bs []blocks.Block) error {
158 + //hash security
159 + for _, b := range bs {
160 + err := verifcid.ValidateCid(b.Cid())
161 + if err != nil {
162 + return err
163 + }
164 + }
165 var toput []blocks.Block
166 if s.checkFirst {
167 toput = make([]blocks.Block, 0, len(bs))
@@ -189,10 +202,15 @@ func (s *blockService) GetBlock(ctx context.Context, c *cid.Cid) (blocks.Block,
202 f = s.exchange
203 }
204
192 - return getBlock(ctx, c, s.blockstore, f)
205 + return getBlock(ctx, c, s.blockstore, f) //hash security
206 }
207
208 func getBlock(ctx context.Context, c *cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) (blocks.Block, error) {
209 + err := verifcid.ValidateCid(c)
210 + if err != nil {
211 + return nil, err
212 + }
213 +
214 block, err := bs.Get(c)
215 if err == nil {
216 return block, nil
@@ -224,11 +242,18 @@ func getBlock(ctx context.Context, c *cid.Cid, bs blockstore.Blockstore, f excha
242 // the returned channel.
243 // NB: No guarantees are made about order.
244 func (s *blockService) GetBlocks(ctx context.Context, ks []*cid.Cid) <-chan blocks.Block {
227 - return getBlocks(ctx, ks, s.blockstore, s.exchange)
245 + return getBlocks(ctx, ks, s.blockstore, s.exchange) //hash security
246 }
247
248 func getBlocks(ctx context.Context, ks []*cid.Cid, bs blockstore.Blockstore, f exchange.Fetcher) <-chan blocks.Block {
249 out := make(chan blocks.Block)
250 + for _, c := range ks {
251 + // hash security
252 + if err := verifcid.ValidateCid(c); err != nil {
253 + log.Errorf("unsafe CID (%s) passed to blockService.GetBlocks: %s", c, err)
254 + }
255 + }
256 +
257 go func() {
258 defer close(out)
259 var misses []*cid.Cid
@@ -285,12 +310,12 @@ type Session struct {
310
311 // GetBlock gets a block in the context of a request session
312 func (s *Session) GetBlock(ctx context.Context, c *cid.Cid) (blocks.Block, error) {
288 - return getBlock(ctx, c, s.bs, s.ses)
313 + return getBlock(ctx, c, s.bs, s.ses) // hash security
314 }
315
316 // GetBlocks gets blocks in the context of a request session
317 func (s *Session) GetBlocks(ctx context.Context, ks []*cid.Cid) <-chan blocks.Block {
293 - return getBlocks(ctx, ks, s.bs, s.ses)
318 + return getBlocks(ctx, ks, s.bs, s.ses) // hash security
319 }
320
321 var _ BlockGetter = (*Session)(nil)
core/builder.go
+5
@@ -15,6 +15,7 @@ import (
15 dag "github.com/ipfs/go-ipfs/merkledag"
16 resolver "github.com/ipfs/go-ipfs/path/resolver"
17 pin "github.com/ipfs/go-ipfs/pin"
18 + "github.com/ipfs/go-ipfs/removeme/verifbs"
19 repo "github.com/ipfs/go-ipfs/repo"
20 cfg "github.com/ipfs/go-ipfs/repo/config"
21 uio "github.com/ipfs/go-ipfs/unixfs/io"
@@ -170,7 +171,9 @@ func setupNode(ctx context.Context, n *IpfsNode, cfg *BuildCfg) error {
171 TempErrFunc: isTooManyFDError,
172 }
173
174 + //hash security
175 bs := bstore.NewBlockstore(rds)
176 + bs = &verifbs.VerifBS{bs}
177
178 opts := bstore.DefaultCacheOpts()
179 conf, err := n.Repo.Config()
@@ -196,8 +199,10 @@ func setupNode(ctx context.Context, n *IpfsNode, cfg *BuildCfg) error {
199 n.Blockstore = bstore.NewGCBlockstore(cbs, n.GCLocker)
200
201 if conf.Experimental.FilestoreEnabled {
202 + // hash security
203 n.Filestore = filestore.NewFilestore(bs, n.Repo.FileManager())
204 n.Blockstore = bstore.NewGCBlockstore(n.Filestore, n.GCLocker)
205 + n.Blockstore = &verifbs.VerifBSGC{n.Blockstore}
206 }
207
208 rcfg, err := n.Repo.Config()
core/commands/add.go
+1 -1
@@ -258,7 +258,7 @@ You can now check what blocks have been created by:
258 exch = offline.Exchange(addblockstore)
259 }
260
261 - bserv := blockservice.New(addblockstore, exch)
261 + bserv := blockservice.New(addblockstore, exch) //hash security 001
262 dserv := dag.NewDAGService(bserv)
263
264 outChan := make(chan interface{}, adderOutChanSize)
removeme/verifbs/verifbs.go new
+63
@@ -0,0 +1,63 @@
1 +package verifbs
2 +
3 +import (
4 + "github.com/ipfs/go-ipfs/removeme/verifcid"
5 +
6 + bstore "gx/ipfs/QmTVDM4LCSUMFNQzbDLL9zQwp8usE6QHymFdh3h8vL9v6b/go-ipfs-blockstore"
7 + cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
8 + blocks "gx/ipfs/Qmej7nf81hi2x2tvjRBF3mcp74sQyuDH4VMYDGd1YtXjb2/go-block-format"
9 +)
10 +
11 +type VerifBSGC struct {
12 + bstore.GCBlockstore
13 +}
14 +
15 +func (bs *VerifBSGC) Put(b blocks.Block) error {
16 + if err := verifcid.ValidateCid(b.Cid()); err != nil {
17 + return err
18 + }
19 + return bs.GCBlockstore.Put(b)
20 +}
21 +
22 +func (bs *VerifBSGC) PutMany(blks []blocks.Block) error {
23 + for _, b := range blks {
24 + if err := verifcid.ValidateCid(b.Cid()); err != nil {
25 + return err
26 + }
27 + }
28 + return bs.GCBlockstore.PutMany(blks)
29 +}
30 +
31 +func (bs *VerifBSGC) Get(c *cid.Cid) (blocks.Block, error) {
32 + if err := verifcid.ValidateCid(c); err != nil {
33 + return nil, err
34 + }
35 + return bs.GCBlockstore.Get(c)
36 +}
37 +
38 +type VerifBS struct {
39 + bstore.Blockstore
40 +}
41 +
42 +func (bs *VerifBS) Put(b blocks.Block) error {
43 + if err := verifcid.ValidateCid(b.Cid()); err != nil {
44 + return err
45 + }
46 + return bs.Blockstore.Put(b)
47 +}
48 +
49 +func (bs *VerifBS) PutMany(blks []blocks.Block) error {
50 + for _, b := range blks {
51 + if err := verifcid.ValidateCid(b.Cid()); err != nil {
52 + return err
53 + }
54 + }
55 + return bs.Blockstore.PutMany(blks)
56 +}
57 +
58 +func (bs *VerifBS) Get(c *cid.Cid) (blocks.Block, error) {
59 + if err := verifcid.ValidateCid(c); err != nil {
60 + return nil, err
61 + }
62 + return bs.Blockstore.Get(c)
63 +}
test/sharness/t0050-block.sh
+2 -2
@@ -185,11 +185,11 @@ test_expect_success "block get output looks right" '
185 '
186
187 test_expect_success "can set multihash type and length on block put" '
188 - HASH=$(echo "foooo" | ipfs block put --format=raw --mhtype=sha3 --mhlen=16)
188 + HASH=$(echo "foooo" | ipfs block put --format=raw --mhtype=sha3 --mhlen=20)
189 '
190
191 test_expect_success "output looks good" '
192 - test "z25ScPysKoxJBcPxczn9NvuHiZU5" = "$HASH"
192 + test "z83bYcqyBkbx5fuNAcvbdv4pr5RYQiEpK" = "$HASH"
193 '
194
195 test_expect_success "can read block with different hash" '