diff options
| -rw-r--r-- | cli_args.go | 4 | ||||
| -rw-r--r-- | init_dir.go | 4 | ||||
| -rw-r--r-- | internal/fusefrontend/args.go | 4 | ||||
| -rw-r--r-- | internal/fusefrontend/ctlsock_interface.go | 4 | ||||
| -rw-r--r-- | internal/fusefrontend/node_dir_ops.go | 111 | ||||
| -rw-r--r-- | internal/fusefrontend/node_prepare_syscall.go | 3 | ||||
| -rw-r--r-- | internal/fusefrontend/xattr_unit_test.go | 2 | ||||
| -rw-r--r-- | internal/nametransform/diriv.go | 22 | ||||
| -rw-r--r-- | internal/nametransform/longnames.go | 4 | ||||
| -rw-r--r-- | internal/nametransform/names.go | 14 | ||||
| -rw-r--r-- | mount.go | 35 | ||||
| -rw-r--r-- | tests/deterministic_names/deterministic_names_test.go | 79 | ||||
| -rw-r--r-- | tests/matrix/matrix_test.go | 13 | ||||
| -rw-r--r-- | tests/test_helpers/helpers.go | 2 | ||||
| -rw-r--r-- | tests/zerodiriv/zerodiriv_test.go | 85 | 
15 files changed, 208 insertions, 178 deletions
| diff --git a/cli_args.go b/cli_args.go index 76e8d30..d7e3217 100644 --- a/cli_args.go +++ b/cli_args.go @@ -30,7 +30,7 @@ type argContainer struct {  	plaintextnames, quiet, nosyslog, wpanic,  	longnames, allow_other, reverse, aessiv, nonempty, raw64,  	noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info, -	sharedstorage, devrandom, fsck, one_file_system, zerodiriv bool +	sharedstorage, devrandom, fsck, one_file_system, deterministic_names bool  	// Mount options with opposites  	dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache, acl bool  	masterkey, mountpoint, cipherdir, cpuprofile, @@ -179,7 +179,7 @@ func parseCliOpts(osArgs []string) (args argContainer) {  	flagSet.BoolVar(&args.devrandom, "devrandom", false, "Use /dev/random for generating master key")  	flagSet.BoolVar(&args.fsck, "fsck", false, "Run a filesystem check on CIPHERDIR")  	flagSet.BoolVar(&args.one_file_system, "one-file-system", false, "Don't cross filesystem boundaries") -	flagSet.BoolVar(&args.zerodiriv, "zerodiriv", false, "Create diriv as all-zero files") +	flagSet.BoolVar(&args.deterministic_names, "deterministic-names", false, "Disable diriv file name randomisation")  	// Mount options with opposites  	flagSet.BoolVar(&args.dev, "dev", false, "Allow device files") diff --git a/init_dir.go b/init_dir.go index ce5f98d..cea7e53 100644 --- a/init_dir.go +++ b/init_dir.go @@ -99,11 +99,11 @@ func initDir(args *argContainer) {  	}  	// Forward mode with filename encryption enabled needs a gocryptfs.diriv file  	// in the root dir -	if !args.plaintextnames && !args.reverse { +	if !args.plaintextnames && !args.reverse && !args.deterministic_names {  		// Open cipherdir (following symlinks)  		dirfd, err := syscall.Open(args.cipherdir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)  		if err == nil { -			err = nametransform.WriteDirIVAt(dirfd, !args.zerodiriv) +			err = nametransform.WriteDirIVAt(dirfd)  			syscall.Close(dirfd)  		}  		if err != nil { diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go index 02ffddb..e20987b 100644 --- a/internal/fusefrontend/args.go +++ b/internal/fusefrontend/args.go @@ -53,6 +53,6 @@ type Args struct {  	// like rsync's `--one-file-system` does.  	// Only applicable to reverse mode.  	OneFileSystem bool -	// ZeroDirIV creates diriv files as all-zero files -	ZeroDirIV bool +	// DeterministicNames disables gocryptfs.diriv files +	DeterministicNames bool  } diff --git a/internal/fusefrontend/ctlsock_interface.go b/internal/fusefrontend/ctlsock_interface.go index 9e8cffc..87f0dc3 100644 --- a/internal/fusefrontend/ctlsock_interface.go +++ b/internal/fusefrontend/ctlsock_interface.go @@ -32,7 +32,7 @@ func (rn *RootNode) EncryptPath(plainPath string) (cipherPath string, err error)  	parts := strings.Split(plainPath, "/")  	wd := dirfd  	for i, part := range parts { -		dirIV, err := nametransform.ReadDirIVAt(wd) +		dirIV, err := rn.nameTransform.ReadDirIVAt(wd)  		if err != nil {  			return "", err  		} @@ -78,7 +78,7 @@ func (rn *RootNode) DecryptPath(cipherPath string) (plainPath string, err error)  	parts := strings.Split(cipherPath, "/")  	wd := dirfd  	for i, part := range parts { -		dirIV, err := nametransform.ReadDirIVAt(wd) +		dirIV, err := rn.nameTransform.ReadDirIVAt(wd)  		if err != nil {  			return "", err  		} diff --git a/internal/fusefrontend/node_dir_ops.go b/internal/fusefrontend/node_dir_ops.go index b43a4e4..c4ab861 100644 --- a/internal/fusefrontend/node_dir_ops.go +++ b/internal/fusefrontend/node_dir_ops.go @@ -34,9 +34,14 @@ func haveDsstore(entries []fuse.DirEntry) bool {  // mkdirWithIv - create a new directory and corresponding diriv file. dirfd  // should be a handle to the parent directory, cName is the name of the new  // directory and mode specifies the access permissions to use. +// If DeterministicNames is set, the diriv file is NOT created.  func (n *Node) mkdirWithIv(dirfd int, cName string, mode uint32, context *fuse.Context) error { -  	rn := n.rootNode() + +	if rn.args.DeterministicNames { +		return syscallcompat.MkdiratUser(dirfd, cName, mode, context) +	} +  	// Between the creation of the directory and the creation of gocryptfs.diriv  	// the directory is inconsistent. Take the lock to prevent other readers  	// from seeing it. @@ -49,7 +54,7 @@ func (n *Node) mkdirWithIv(dirfd int, cName string, mode uint32, context *fuse.C  	dirfd2, err := syscallcompat.Openat(dirfd, cName, syscall.O_DIRECTORY|syscall.O_NOFOLLOW|syscallcompat.O_PATH, 0)  	if err == nil {  		// Create gocryptfs.diriv -		err = nametransform.WriteDirIVAt(dirfd2, !rn.args.ZeroDirIV) +		err = nametransform.WriteDirIVAt(dirfd2)  		syscall.Close(dirfd2)  	}  	if err != nil { @@ -90,62 +95,67 @@ func (n *Node) Mkdir(ctx context.Context, name string, mode uint32, out *fuse.En  			return nil, fs.ToErrno(err)  		}  		st = syscallcompat.Unix2syscall(ust) -	} else { -		// We need write and execute permissions to create gocryptfs.diriv. -		// Also, we need read permissions to open the directory (to avoid -		// race-conditions between getting and setting the mode). -		origMode := mode -		mode = mode | 0700 -		// Handle long file name -		if nametransform.IsLongContent(cName) { -			// Create ".name" -			err := rn.nameTransform.WriteLongNameAt(dirfd, cName, name) -			if err != nil { -				return nil, fs.ToErrno(err) -			} +		// Create child node & return +		ch := n.newChild(ctx, &st, out) +		return ch, 0 -			// Create directory -			err = rn.mkdirWithIv(dirfd, cName, mode, context) -			if err != nil { -				nametransform.DeleteLongNameAt(dirfd, cName) -				return nil, fs.ToErrno(err) -			} -		} else { -			err := rn.mkdirWithIv(dirfd, cName, mode, context) -			if err != nil { -				return nil, fs.ToErrno(err) -			} -		} +	} + +	// We need write and execute permissions to create gocryptfs.diriv. +	// Also, we need read permissions to open the directory (to avoid +	// race-conditions between getting and setting the mode). +	origMode := mode +	mode = mode | 0700 -		fd, err := syscallcompat.Openat(dirfd, cName, -			syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0) +	// Handle long file name +	if nametransform.IsLongContent(cName) { +		// Create ".name" +		err := rn.nameTransform.WriteLongNameAt(dirfd, cName, name)  		if err != nil { -			tlog.Warn.Printf("Mkdir %q: Openat failed: %v", cName, err)  			return nil, fs.ToErrno(err)  		} -		defer syscall.Close(fd) - -		err = syscall.Fstat(fd, &st) +		// Create directory & rollback .name file on error +		err = rn.mkdirWithIv(dirfd, cName, mode, context) +		if err != nil { +			nametransform.DeleteLongNameAt(dirfd, cName) +			return nil, fs.ToErrno(err) +		} +	} else { +		err := rn.mkdirWithIv(dirfd, cName, mode, context)  		if err != nil { -			tlog.Warn.Printf("Mkdir %q: Fstat failed: %v", cName, err)  			return nil, fs.ToErrno(err)  		} +	} -		// Fix permissions -		if origMode != mode { -			// Preserve SGID bit if it was set due to inheritance. -			origMode = uint32(st.Mode&^0777) | origMode -			err = syscall.Fchmod(fd, origMode) -			if err != nil { -				tlog.Warn.Printf("Mkdir %q: Fchmod %#o -> %#o failed: %v", cName, mode, origMode, err) -			} +	// Fill `st` +	fd, err := syscallcompat.Openat(dirfd, cName, +		syscall.O_RDONLY|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0) +	if err != nil { +		tlog.Warn.Printf("Mkdir %q: Openat failed: %v", cName, err) +		return nil, fs.ToErrno(err) +	} +	defer syscall.Close(fd) + +	err = syscall.Fstat(fd, &st) +	if err != nil { +		tlog.Warn.Printf("Mkdir %q: Fstat failed: %v", cName, err) +		return nil, fs.ToErrno(err) +	} + +	// Fix permissions +	if origMode != mode { +		// Preserve SGID bit if it was set due to inheritance. +		origMode = uint32(st.Mode&^0777) | origMode +		err = syscall.Fchmod(fd, origMode) +		if err != nil { +			tlog.Warn.Printf("Mkdir %q: Fchmod %#o -> %#o failed: %v", cName, mode, origMode, err)  		} +  	} -	// Create child node +	// Create child node & return  	ch := n.newChild(ctx, &st, out) -  	return ch, 0  } @@ -175,7 +185,7 @@ func (n *Node) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {  	rn := n.rootNode()  	if !rn.args.PlaintextNames {  		// Read the DirIV from disk -		cachedIV, err = nametransform.ReadDirIVAt(fd) +		cachedIV, err = rn.nameTransform.ReadDirIVAt(fd)  		if err != nil {  			tlog.Warn.Printf("OpenDir %q: could not read %s: %v", cDirName, nametransform.DirIVFilename, err)  			return nil, syscall.EIO @@ -196,7 +206,7 @@ func (n *Node) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {  			plain = append(plain, cipherEntries[i])  			continue  		} -		if cName == nametransform.DirIVFilename { +		if !rn.args.DeterministicNames && cName == nametransform.DirIVFilename {  			// silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled  			continue  		} @@ -249,6 +259,15 @@ func (n *Node) Rmdir(ctx context.Context, name string) (code syscall.Errno) {  		err := unix.Unlinkat(parentDirFd, cName, unix.AT_REMOVEDIR)  		return fs.ToErrno(err)  	} +	if rn.args.DeterministicNames { +		if err := unix.Unlinkat(parentDirFd, cName, unix.AT_REMOVEDIR); err != nil { +			return fs.ToErrno(err) +		} +		if nametransform.IsLongContent(cName) { +			nametransform.DeleteLongNameAt(parentDirFd, cName) +		} +		return 0 +	}  	// Unless we are running as root, we need read, write and execute permissions  	// to handle gocryptfs.diriv.  	permWorkaround := false diff --git a/internal/fusefrontend/node_prepare_syscall.go b/internal/fusefrontend/node_prepare_syscall.go index 0894379..8a0e75c 100644 --- a/internal/fusefrontend/node_prepare_syscall.go +++ b/internal/fusefrontend/node_prepare_syscall.go @@ -8,7 +8,6 @@ import (  	"github.com/hanwen/go-fuse/v2/fs" -	"github.com/rfjakob/gocryptfs/internal/nametransform"  	"github.com/rfjakob/gocryptfs/internal/syscallcompat"  ) @@ -73,7 +72,7 @@ func (n *Node) prepareAtSyscall(child string) (dirfd int, cName string, errno sy  	// Cache store  	if !rn.args.PlaintextNames {  		var err error -		iv, err = nametransform.ReadDirIVAt(dirfd) +		iv, err = rn.nameTransform.ReadDirIVAt(dirfd)  		if err != nil {  			syscall.Close(dirfd)  			return -1, "", fs.ToErrno(err) diff --git a/internal/fusefrontend/xattr_unit_test.go b/internal/fusefrontend/xattr_unit_test.go index c48781c..397e3ef 100644 --- a/internal/fusefrontend/xattr_unit_test.go +++ b/internal/fusefrontend/xattr_unit_test.go @@ -19,7 +19,7 @@ func newTestFS(args Args) *RootNode {  	key := make([]byte, cryptocore.KeyLen)  	cCore := cryptocore.New(key, cryptocore.BackendGoGCM, contentenc.DefaultIVBits, true, false)  	cEnc := contentenc.New(cCore, contentenc.DefaultBS, false) -	n := nametransform.New(cCore.EMECipher, true, true, nil) +	n := nametransform.New(cCore.EMECipher, true, true, nil, false)  	rn := NewRootNode(args, cEnc, n)  	oneSec := time.Second  	options := &fs.Options{ diff --git a/internal/nametransform/diriv.go b/internal/nametransform/diriv.go index a288aa5..3a80baa 100644 --- a/internal/nametransform/diriv.go +++ b/internal/nametransform/diriv.go @@ -1,6 +1,7 @@  package nametransform  import ( +	"bytes"  	"fmt"  	"io"  	"os" @@ -22,7 +23,11 @@ const (  // ReadDirIVAt reads "gocryptfs.diriv" from the directory that is opened as "dirfd".  // Using the dirfd makes it immune to concurrent renames of the directory.  // Retries on EINTR. -func ReadDirIVAt(dirfd int) (iv []byte, err error) { +// If deterministicNames is set it returns an all-zero slice. +func (n *NameTransform) ReadDirIVAt(dirfd int) (iv []byte, err error) { +	if n.deterministicNames { +		return make([]byte, DirIVLen), nil +	}  	fdRaw, err := syscallcompat.Openat(dirfd, DirIVFilename,  		syscall.O_RDONLY|syscall.O_NOFOLLOW, 0)  	if err != nil { @@ -33,6 +38,9 @@ func ReadDirIVAt(dirfd int) (iv []byte, err error) {  	return fdReadDirIV(fd)  } +// allZeroDirIV is preallocated to quickly check if the data read from disk is all zero +var allZeroDirIV = make([]byte, DirIVLen) +  // fdReadDirIV reads and verifies the DirIV from an opened gocryptfs.diriv file.  func fdReadDirIV(fd *os.File) (iv []byte, err error) {  	// We want to detect if the file is bigger than DirIVLen, so @@ -46,6 +54,9 @@ func fdReadDirIV(fd *os.File) (iv []byte, err error) {  	if len(iv) != DirIVLen {  		return nil, fmt.Errorf("wanted %d bytes, got %d", DirIVLen, len(iv))  	} +	if bytes.Equal(iv, allZeroDirIV) { +		return nil, fmt.Errorf("diriv is all-zero") +	}  	return iv, nil  } @@ -53,13 +64,8 @@ func fdReadDirIV(fd *os.File) (iv []byte, err error) {  // "dirfd". On error we try to delete the incomplete file.  // This function is exported because it is used from fusefrontend, main,  // and also the automated tests. -func WriteDirIVAt(dirfd int, randomInitialization bool) error { -	var iv []byte -	if randomInitialization { -		iv = cryptocore.RandBytes(DirIVLen) -	} else { -		iv = make([]byte, DirIVLen) -	} +func WriteDirIVAt(dirfd int) error { +	iv := cryptocore.RandBytes(DirIVLen)  	// 0400 permissions: gocryptfs.diriv should never be modified after creation.  	// Don't use "ioutil.WriteFile", it causes trouble on NFS:  	// https://github.com/rfjakob/gocryptfs/commit/7d38f80a78644c8ec4900cc990bfb894387112ed diff --git a/internal/nametransform/longnames.go b/internal/nametransform/longnames.go index 74ddb07..bf8060b 100644 --- a/internal/nametransform/longnames.go +++ b/internal/nametransform/longnames.go @@ -114,7 +114,7 @@ func ReadLongNameAt(dirfd int, cName string) (string, error) {  func DeleteLongNameAt(dirfd int, hashName string) error {  	err := syscallcompat.Unlinkat(dirfd, hashName+LongNameSuffix, 0)  	if err != nil { -		tlog.Warn.Printf("DeleteLongName: %v", err) +		tlog.Warn.Printf("DeleteLongNameAt: %v", err)  	}  	return err  } @@ -128,7 +128,7 @@ func (n *NameTransform) WriteLongNameAt(dirfd int, hashName string, plainName st  	plainName = filepath.Base(plainName)  	// Encrypt the basename -	dirIV, err := ReadDirIVAt(dirfd) +	dirIV, err := n.ReadDirIVAt(dirfd)  	if err != nil {  		return err  	} diff --git a/internal/nametransform/names.go b/internal/nametransform/names.go index 566f0c7..412ccc0 100644 --- a/internal/nametransform/names.go +++ b/internal/nametransform/names.go @@ -25,11 +25,12 @@ type NameTransform struct {  	// on the Raw64 feature flag  	B64 *base64.Encoding  	// Patterns to bypass decryption -	badnamePatterns []string +	badnamePatterns    []string +	deterministicNames bool  }  // New returns a new NameTransform instance. -func New(e *eme.EMECipher, longNames bool, raw64 bool, badname []string) *NameTransform { +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) @@ -38,10 +39,11 @@ func New(e *eme.EMECipher, longNames bool, raw64 bool, badname []string) *NameTr  		b64 = base64.RawURLEncoding  	}  	return &NameTransform{ -		emeCipher:       e, -		longNames:       longNames, -		B64:             b64, -		badnamePatterns: badname, +		emeCipher:          e, +		longNames:          longNames, +		B64:                b64, +		badnamePatterns:    badname, +		deterministicNames: deterministicNames,  	}  } @@ -261,22 +261,22 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f  		args.allow_other = true  	}  	frontendArgs := fusefrontend.Args{ -		Cipherdir:       args.cipherdir, -		PlaintextNames:  args.plaintextnames, -		LongNames:       args.longnames, -		ConfigCustom:    args._configCustom, -		NoPrealloc:      args.noprealloc, -		SerializeReads:  args.serialize_reads, -		ForceDecode:     args.forcedecode, -		ForceOwner:      args._forceOwner, -		Exclude:         args.exclude, -		ExcludeWildcard: args.excludeWildcard, -		ExcludeFrom:     args.excludeFrom, -		Suid:            args.suid, -		KernelCache:     args.kernel_cache, -		SharedStorage:   args.sharedstorage, -		OneFileSystem:   args.one_file_system, -		ZeroDirIV:       args.zerodiriv, +		Cipherdir:          args.cipherdir, +		PlaintextNames:     args.plaintextnames, +		LongNames:          args.longnames, +		ConfigCustom:       args._configCustom, +		NoPrealloc:         args.noprealloc, +		SerializeReads:     args.serialize_reads, +		ForceDecode:        args.forcedecode, +		ForceOwner:         args._forceOwner, +		Exclude:            args.exclude, +		ExcludeWildcard:    args.excludeWildcard, +		ExcludeFrom:        args.excludeFrom, +		Suid:               args.suid, +		KernelCache:        args.kernel_cache, +		SharedStorage:      args.sharedstorage, +		OneFileSystem:      args.one_file_system, +		DeterministicNames: args.deterministic_names,  	}  	// confFile is nil when "-zerokey" or "-masterkey" was used  	if confFile != nil { @@ -300,7 +300,8 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f  	// Init crypto backend  	cCore := cryptocore.New(masterkey, cryptoBackend, contentenc.DefaultIVBits, args.hkdf, args.forcedecode)  	cEnc := contentenc.New(cCore, contentenc.DefaultBS, args.forcedecode) -	nameTransform := nametransform.New(cCore.EMECipher, frontendArgs.LongNames, args.raw64, []string(args.badname)) +	nameTransform := nametransform.New(cCore.EMECipher, frontendArgs.LongNames, +		args.raw64, []string(args.badname), frontendArgs.DeterministicNames)  	// After the crypto backend is initialized,  	// we can purge the master key from memory.  	for i := range masterkey { diff --git a/tests/deterministic_names/deterministic_names_test.go b/tests/deterministic_names/deterministic_names_test.go new file mode 100644 index 0000000..1b355df --- /dev/null +++ b/tests/deterministic_names/deterministic_names_test.go @@ -0,0 +1,79 @@ +package deterministic_names + +// integration tests that target "-deterministic-names" specifically + +import ( +	"io/ioutil" +	"os" +	"path/filepath" +	"testing" + +	"github.com/rfjakob/gocryptfs/tests/test_helpers" +) + +var cDir string +var pDir string + +var testPw = []byte("test") + +// Create and mount "-deterministic-names" fs +func TestMain(m *testing.M) { +	cDir = test_helpers.InitFS(nil, "-deterministic-names") +	pDir = cDir + ".mnt" +	test_helpers.MountOrExit(cDir, pDir, "-deterministic-names", "-extpass", "echo test") +	r := m.Run() +	test_helpers.UnmountPanic(pDir) +	os.Exit(r) +} + +// TestDeterministicNames checks that a file with the same plaintext name +// always encrypts to the same ciphertext name +func TestDeterministicNames(t *testing.T) { +	// "foo" should encrypt to the same name in both directories +	if err := os.MkdirAll(pDir+"/x/foo", 0700); err != nil { +		t.Fatal(err) +	} +	if err := os.MkdirAll(pDir+"/y/foo", 0700); err != nil { +		t.Fatal(err) +	} +	matches, err := filepath.Glob(cDir + "/*/*") +	if err != nil || len(matches) != 2 { +		t.Fatal(matches, err) +	} +	if filepath.Base(matches[0]) != filepath.Base(matches[1]) { +		t.Error(matches) +	} +	fooEncrypted := filepath.Base(matches[0]) + +	// "foo" should also encrypt to the same name in the root directory +	if err := os.Mkdir(pDir+"/foo", 0700); err != nil { +		t.Fatal(err) +	} +	_, err = os.Stat(cDir + "/" + fooEncrypted) +	if err != nil { +		t.Error(err) +	} + +	// Replace directory with file +	if err := os.RemoveAll(pDir + "/foo"); err != nil { +		t.Fatal(err) +	} +	if err := ioutil.WriteFile(pDir+"/foo", nil, 0700); err != nil { +		t.Fatal(err) +	} +	_, err = os.Stat(cDir + "/" + fooEncrypted) +	if err != nil { +		t.Error(err) +	} + +	// Rename back and forth, name should stay the same +	if err := os.Rename(pDir+"/foo", pDir+"/foo.tmp"); err != nil { +		t.Fatal(err) +	} +	if err := os.Rename(pDir+"/foo.tmp", pDir+"/foo"); err != nil { +		t.Fatal(err) +	} +	if _, err := os.Stat(cDir + "/" + fooEncrypted); err != nil { +		t.Error(err) +	} +} diff --git a/tests/matrix/matrix_test.go b/tests/matrix/matrix_test.go index 5cc5251..c51b391 100644 --- a/tests/matrix/matrix_test.go +++ b/tests/matrix/matrix_test.go @@ -55,20 +55,28 @@ var matrix = []testcaseMatrix{  	// -serialize_reads  	{false, "auto", false, false, []string{"-serialize_reads"}},  	{false, "auto", false, false, []string{"-sharedstorage"}}, +	{false, "auto", false, false, []string{"-deterministic-names"}},  }  // This is the entry point for the tests  func TestMain(m *testing.M) {  	// Make "testing.Verbose()" return the correct value  	flag.Parse() -	for _, testcase = range matrix { +	var i int +	for i, testcase = range matrix {  		if testcase.openssl == "true" && stupidgcm.BuiltWithoutOpenssl {  			continue  		}  		if testing.Verbose() {  			fmt.Printf("matrix: testcase = %#v\n", testcase)  		} -		test_helpers.ResetTmpDir(!testcase.plaintextnames) +		createDirIV := true +		if testcase.plaintextnames { +			createDirIV = false +		} else if len(testcase.extraArgs) == 1 && testcase.extraArgs[0] == "-deterministic-names" { +			createDirIV = false +		} +		test_helpers.ResetTmpDir(createDirIV)  		opts := []string{"-zerokey"}  		//opts = append(opts, "-fusedebug")  		opts = append(opts, fmt.Sprintf("-openssl=%v", testcase.openssl)) @@ -90,6 +98,7 @@ func TestMain(m *testing.M) {  		}  		test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)  		if r != 0 { +			fmt.Printf("TestMain: matrix[%d] = %#v failed\n", i, testcase)  			os.Exit(r)  		}  	} diff --git a/tests/test_helpers/helpers.go b/tests/test_helpers/helpers.go index f78c59c..87dba0a 100644 --- a/tests/test_helpers/helpers.go +++ b/tests/test_helpers/helpers.go @@ -110,7 +110,7 @@ func ResetTmpDir(createDirIV bool) {  		// Open cipherdir (following symlinks)  		dirfd, err := syscall.Open(DefaultCipherDir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)  		if err == nil { -			err = nametransform.WriteDirIVAt(dirfd, true) +			err = nametransform.WriteDirIVAt(dirfd)  			syscall.Close(dirfd)  		}  		if err != nil { diff --git a/tests/zerodiriv/zerodiriv_test.go b/tests/zerodiriv/zerodiriv_test.go deleted file mode 100644 index 3fbbf47..0000000 --- a/tests/zerodiriv/zerodiriv_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package zerodiriv - -// integration tests that target zerodiriv specifically - -import ( -	"bytes" -	"path/filepath" -	"io/ioutil" -	"os" -	"testing" - -	"github.com/rfjakob/gocryptfs/tests/test_helpers" -) - -var cDir string -var pDir string - -var testPw = []byte("test") - -// Create and mount "-zerodiriv" fs -func TestMain(m *testing.M) { -	cDir = test_helpers.InitFS(nil, "-zerodiriv") -	pDir = cDir + ".mnt" -	test_helpers.MountOrExit(cDir, pDir, "-zerodiriv", "-extpass", "echo test") -	r := m.Run() -	test_helpers.UnmountPanic(pDir) -	os.Exit(r) -} - -// diriv should be all-zero on newly created dirs -func TestZeroDirIV(t *testing.T) { -	// Create /dir1, move it and create it again -	var dirPath = pDir+"/dir1" -	var err = os.Mkdir(dirPath, 0777) -	if err != nil { -		t.Error(err) -	} -	err = os.Rename(dirPath, dirPath + ".bak") -	if err != nil { -		t.Error(err) -	} -	err = os.Mkdir(dirPath, 0777) -	if err != nil { -		t.Error(err) -	} - -	var matches []string -	matches, err = filepath.Glob(cDir+"/*/gocryptfs.diriv") -	if err != nil { -		t.Error(err) -	} - -	// The contents of the both diriv files must be the same -	var diriv0 []byte -	diriv0, err = ioutil.ReadFile(matches[0]) -	if err != nil { -		t.Error(err) -	} -	var diriv1 []byte -	diriv1, err = ioutil.ReadFile(matches[1]) -	if err != nil { -		t.Error(err) -	} -	if !bytes.Equal(diriv0, diriv1) { -		t.Errorf("both dirivs should have the same value") -	} -	// And equal to zero -	zerodiriv := make([]byte, len(diriv0)) -	if !bytes.Equal(diriv0, zerodiriv) { -		t.Errorf("both dirivs should be all-zero") -	} -} - -// root diriv should be all-zero -func TestZeroRootDirIV(t *testing.T) { -	// The contents of the diriv file must be zero -	diriv, err := ioutil.ReadFile(cDir+"/gocryptfs.diriv") -	if err != nil { -		t.Error(err) -	} -	zerodiriv := make([]byte, len(diriv)) -	if !bytes.Equal(diriv, zerodiriv) { -		t.Errorf("root diriv should be all-zero") -	} -} | 
