lib/model: Verify request content against weak (and possibly strong) hash (#4767)
This commit is contained in:
committed by
Jakob Borg
parent
678c80ffe4
commit
ef0dcea6a4
@@ -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 := ¶llelHasher{
|
||||
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
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user