lib/model: Verify request content against weak (and possibly strong) hash (#4767)

This commit is contained in:
Audrius Butkevicius
2018-05-05 09:24:44 +01:00
committed by Jakob Borg
parent 678c80ffe4
commit ef0dcea6a4
27 changed files with 518 additions and 454 deletions

View File

@@ -62,26 +62,24 @@ func HashFile(ctx context.Context, fs fs.Filesystem, path string, blockSize int,
// workers are used in parallel. The outbox will become closed when the inbox
// is closed and all items handled.
type parallelHasher struct {
fs fs.Filesystem
workers int
outbox chan<- protocol.FileInfo
inbox <-chan protocol.FileInfo
counter Counter
done chan<- struct{}
useWeakHashes bool
wg sync.WaitGroup
fs fs.Filesystem
workers int
outbox chan<- protocol.FileInfo
inbox <-chan protocol.FileInfo
counter Counter
done chan<- struct{}
wg sync.WaitGroup
}
func newParallelHasher(ctx context.Context, fs fs.Filesystem, workers int, outbox chan<- protocol.FileInfo, inbox <-chan protocol.FileInfo, counter Counter, done chan<- struct{}, useWeakHashes bool) {
func newParallelHasher(ctx context.Context, fs fs.Filesystem, workers int, outbox chan<- protocol.FileInfo, inbox <-chan protocol.FileInfo, counter Counter, done chan<- struct{}) {
ph := &parallelHasher{
fs: fs,
workers: workers,
outbox: outbox,
inbox: inbox,
counter: counter,
done: done,
useWeakHashes: useWeakHashes,
wg: sync.NewWaitGroup(),
fs: fs,
workers: workers,
outbox: outbox,
inbox: inbox,
counter: counter,
done: done,
wg: sync.NewWaitGroup(),
}
for i := 0; i < workers; i++ {
@@ -106,7 +104,7 @@ func (ph *parallelHasher) hashFiles(ctx context.Context) {
panic("Bug. Asked to hash a directory or a deleted file.")
}
blocks, err := HashFile(ctx, ph.fs, f.Name, f.BlockSize(), ph.counter, ph.useWeakHashes)
blocks, err := HashFile(ctx, ph.fs, f.Name, f.BlockSize(), ph.counter, true)
if err != nil {
l.Debugln("hash error:", f.Name, err)
continue

View File

@@ -7,6 +7,7 @@
package scanner
import (
"bytes"
"context"
"hash"
"io"
@@ -107,6 +108,29 @@ func Blocks(ctx context.Context, r io.Reader, blocksize int, sizehint int64, cou
return blocks, nil
}
func Validate(buf, hash []byte, weakHash uint32) bool {
rd := bytes.NewReader(buf)
if weakHash != 0 {
whf := adler32.New()
if _, err := io.Copy(whf, rd); err == nil && whf.Sum32() == weakHash {
return true
}
// Copy error or mismatch, go to next algo.
rd.Seek(0, io.SeekStart)
}
if len(hash) > 0 {
hf := sha256.New()
if _, err := io.Copy(hf, rd); err == nil {
// Sum allocates, so let's hope we don't hit this often.
return bytes.Equal(hf.Sum(nil), hash)
}
}
// Both algos failed or no hashes were specified. Assume it's all good.
return true
}
type noopHash struct{}
func (noopHash) Sum32() uint32 { return 0 }

View File

@@ -64,8 +64,6 @@ type Config struct {
// Optional progress tick interval which defines how often FolderScanProgress
// events are emitted. Negative number means disabled.
ProgressTickIntervalS int
// Whether or not we should also compute weak hashes
UseWeakHashes bool
// Whether to use large blocks for large files or the old standard of 128KiB for everything.
UseLargeBlocks bool
}
@@ -120,7 +118,7 @@ func (w *walker) walk(ctx context.Context) chan protocol.FileInfo {
// We're not required to emit scan progress events, just kick off hashers,
// and feed inputs directly from the walker.
if w.ProgressTickIntervalS < 0 {
newParallelHasher(ctx, w.Filesystem, w.Hashers, finishedChan, toHashChan, nil, nil, w.UseWeakHashes)
newParallelHasher(ctx, w.Filesystem, w.Hashers, finishedChan, toHashChan, nil, nil)
return finishedChan
}
@@ -151,7 +149,7 @@ func (w *walker) walk(ctx context.Context) chan protocol.FileInfo {
done := make(chan struct{})
progress := newByteCounter()
newParallelHasher(ctx, w.Filesystem, w.Hashers, finishedChan, realToHashChan, progress, done, w.UseWeakHashes)
newParallelHasher(ctx, w.Filesystem, w.Hashers, finishedChan, realToHashChan, progress, done)
// A routine which actually emits the FolderScanProgress events
// every w.ProgressTicker ticks, until the hasher routines terminate.