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" '