nametransform: add longNameMax parameter
Determines when to start hashing long names instead of hardcoded 255. Will be used to alleviate "name too long" issues some users see on cloud storage. https://github.com/rfjakob/gocryptfs/issues/499
This commit is contained in:
parent
a652be805e
commit
dc32710045
@ -19,7 +19,7 @@ func newTestFS(args Args) *RootNode {
|
||||
key := make([]byte, cryptocore.KeyLen)
|
||||
cCore := cryptocore.New(key, cryptocore.BackendGoGCM, contentenc.DefaultIVBits, true)
|
||||
cEnc := contentenc.New(cCore, contentenc.DefaultBS)
|
||||
n := nametransform.New(cCore.EMECipher, true, true, nil, false)
|
||||
n := nametransform.New(cCore.EMECipher, true, 0, true, nil, false)
|
||||
rn := NewRootNode(args, cEnc, n)
|
||||
oneSec := time.Second
|
||||
options := &fs.Options{
|
||||
|
@ -48,7 +48,7 @@ func (be *NameTransform) EncryptAndHashBadName(name string, iv []byte, dirfd int
|
||||
//expand suffix on error
|
||||
continue
|
||||
}
|
||||
if be.longNames && len(cName) > NameMax {
|
||||
if len(cName) > be.longNameMax {
|
||||
cNamePart = be.HashLongName(cName)
|
||||
}
|
||||
cNameBadReverse := cNamePart + name[charpos:len(name)-len(BadnameSuffix)]
|
||||
|
@ -1,7 +1,11 @@
|
||||
package nametransform
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/v2/internal/contentenc"
|
||||
"github.com/rfjakob/gocryptfs/v2/internal/cryptocore"
|
||||
)
|
||||
|
||||
func TestIsLongName(t *testing.T) {
|
||||
@ -28,3 +32,40 @@ func TestRemoveLongNameSuffix(t *testing.T) {
|
||||
t.Error(".name suffix not removed")
|
||||
}
|
||||
}
|
||||
|
||||
func newLognamesTestInstance(longNameMax uint8) *NameTransform {
|
||||
key := make([]byte, cryptocore.KeyLen)
|
||||
cCore := cryptocore.New(key, cryptocore.BackendGoGCM, contentenc.DefaultIVBits, true)
|
||||
return New(cCore.EMECipher, true, longNameMax, true, nil, false)
|
||||
}
|
||||
|
||||
func TestLongNameMax(t *testing.T) {
|
||||
iv := make([]byte, 16)
|
||||
for max := 0; max <= NameMax; max++ {
|
||||
n := newLognamesTestInstance(uint8(max))
|
||||
if max == 0 {
|
||||
// effective value is 255
|
||||
max = NameMax
|
||||
}
|
||||
for l := 0; l <= NameMax+10; l++ {
|
||||
name := strings.Repeat("x", l)
|
||||
out, err := n.EncryptAndHashName(name, iv)
|
||||
if l == 0 || l > NameMax {
|
||||
if err == nil {
|
||||
t.Errorf("should have rejected a name of length %d, but did not", l)
|
||||
}
|
||||
continue
|
||||
}
|
||||
cName, _ := n.EncryptName(name, iv)
|
||||
rawLen := len(cName)
|
||||
want := LongNameNone
|
||||
if rawLen > max {
|
||||
want = LongNameContent
|
||||
}
|
||||
have := NameType(out)
|
||||
if have != want {
|
||||
t.Errorf("l=%d max=%d: wanted %v, got %v\nname=%q\nout=%q", l, max, want, have, name, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ package nametransform
|
||||
import (
|
||||
"crypto/aes"
|
||||
"encoding/base64"
|
||||
"math"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
@ -20,7 +21,9 @@ const (
|
||||
// NameTransform is used to transform filenames.
|
||||
type NameTransform struct {
|
||||
emeCipher *eme.EMECipher
|
||||
longNames bool
|
||||
// Names longer than `longNameMax` are hashed. Set to MaxInt when
|
||||
// longnames are disabled.
|
||||
longNameMax int
|
||||
// B64 = either base64.URLEncoding or base64.RawURLEncoding, depending
|
||||
// on the Raw64 feature flag
|
||||
B64 *base64.Encoding
|
||||
@ -30,17 +33,28 @@ type NameTransform struct {
|
||||
}
|
||||
|
||||
// New returns a new NameTransform instance.
|
||||
func New(e *eme.EMECipher, longNames bool, raw64 bool, badname []string, deterministicNames bool) *NameTransform {
|
||||
tlog.Debug.Printf("nametransform.New: longNames=%v, raw64=%v, badname=%q",
|
||||
longNames, raw64, badname)
|
||||
|
||||
//
|
||||
// If `longNames` is set, names longer than `longNameMax` are hashed to
|
||||
// `gocryptfs.longname.[sha256]`.
|
||||
// Pass `longNameMax = 0` to use the default value (255).
|
||||
func New(e *eme.EMECipher, longNames bool, longNameMax uint8, raw64 bool, badname []string, deterministicNames bool) *NameTransform {
|
||||
tlog.Debug.Printf("nametransform.New: longNameMax=%v, raw64=%v, badname=%q",
|
||||
longNameMax, raw64, badname)
|
||||
b64 := base64.URLEncoding
|
||||
if raw64 {
|
||||
b64 = base64.RawURLEncoding
|
||||
}
|
||||
var effectiveLongNameMax int = math.MaxInt
|
||||
if longNames {
|
||||
if longNameMax == 0 {
|
||||
effectiveLongNameMax = NameMax
|
||||
} else {
|
||||
effectiveLongNameMax = int(longNameMax)
|
||||
}
|
||||
}
|
||||
return &NameTransform{
|
||||
emeCipher: e,
|
||||
longNames: longNames,
|
||||
longNameMax: effectiveLongNameMax,
|
||||
B64: b64,
|
||||
badnamePatterns: badname,
|
||||
deterministicNames: deterministicNames,
|
||||
@ -115,7 +129,7 @@ func (be *NameTransform) EncryptAndHashName(name string, iv []byte) (string, err
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if be.longNames && len(cName) > NameMax {
|
||||
if len(cName) > be.longNameMax {
|
||||
return be.HashLongName(cName), nil
|
||||
}
|
||||
return cName, nil
|
||||
|
2
mount.go
2
mount.go
@ -324,7 +324,7 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f
|
||||
// Init crypto backend
|
||||
cCore := cryptocore.New(masterkey, cryptoBackend, IVBits, args.hkdf)
|
||||
cEnc := contentenc.New(cCore, contentenc.DefaultBS)
|
||||
nameTransform := nametransform.New(cCore.EMECipher, frontendArgs.LongNames,
|
||||
nameTransform := nametransform.New(cCore.EMECipher, frontendArgs.LongNames, 0,
|
||||
args.raw64, []string(args.badname), frontendArgs.DeterministicNames)
|
||||
// After the crypto backend is initialized,
|
||||
// we can purge the master key from memory.
|
||||
|
Loading…
Reference in New Issue
Block a user