Flag -zerodiriv to create all diriv as all zero byte files
This commit is contained in:
parent
02c91d73ce
commit
8f94083a21
@ -545,6 +545,11 @@ useful in regression testing.
|
|||||||
|
|
||||||
Applies to: all actions.
|
Applies to: all actions.
|
||||||
|
|
||||||
|
#### -zerodiriv
|
||||||
|
Create diriv as all-zero files
|
||||||
|
|
||||||
|
Applies to: all actions without `-plaintextnames`.
|
||||||
|
|
||||||
#### \-\-
|
#### \-\-
|
||||||
Stop option parsing. Helpful when CIPHERDIR may start with a
|
Stop option parsing. Helpful when CIPHERDIR may start with a
|
||||||
dash "-".
|
dash "-".
|
||||||
|
@ -30,7 +30,7 @@ type argContainer struct {
|
|||||||
plaintextnames, quiet, nosyslog, wpanic,
|
plaintextnames, quiet, nosyslog, wpanic,
|
||||||
longnames, allow_other, reverse, aessiv, nonempty, raw64,
|
longnames, allow_other, reverse, aessiv, nonempty, raw64,
|
||||||
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,
|
noprealloc, speed, hkdf, serialize_reads, forcedecode, hh, info,
|
||||||
sharedstorage, devrandom, fsck, one_file_system bool
|
sharedstorage, devrandom, fsck, one_file_system, zerodiriv bool
|
||||||
// Mount options with opposites
|
// Mount options with opposites
|
||||||
dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache, acl bool
|
dev, nodev, suid, nosuid, exec, noexec, rw, ro, kernel_cache, acl bool
|
||||||
masterkey, mountpoint, cipherdir, cpuprofile,
|
masterkey, mountpoint, cipherdir, cpuprofile,
|
||||||
@ -179,6 +179,7 @@ func parseCliOpts(osArgs []string) (args argContainer) {
|
|||||||
flagSet.BoolVar(&args.devrandom, "devrandom", false, "Use /dev/random for generating master key")
|
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.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.one_file_system, "one-file-system", false, "Don't cross filesystem boundaries")
|
||||||
|
flagSet.BoolVar(&args.zerodiriv, "zerodiriv", false, "Create diriv as all-zero files")
|
||||||
|
|
||||||
// Mount options with opposites
|
// Mount options with opposites
|
||||||
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")
|
flagSet.BoolVar(&args.dev, "dev", false, "Allow device files")
|
||||||
|
@ -103,7 +103,7 @@ func initDir(args *argContainer) {
|
|||||||
// Open cipherdir (following symlinks)
|
// Open cipherdir (following symlinks)
|
||||||
dirfd, err := syscall.Open(args.cipherdir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
|
dirfd, err := syscall.Open(args.cipherdir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = nametransform.WriteDirIVAt(dirfd)
|
err = nametransform.WriteDirIVAt(dirfd, !args.zerodiriv)
|
||||||
syscall.Close(dirfd)
|
syscall.Close(dirfd)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -53,4 +53,6 @@ type Args struct {
|
|||||||
// like rsync's `--one-file-system` does.
|
// like rsync's `--one-file-system` does.
|
||||||
// Only applicable to reverse mode.
|
// Only applicable to reverse mode.
|
||||||
OneFileSystem bool
|
OneFileSystem bool
|
||||||
|
// ZeroDirIV creates diriv files as all-zero files
|
||||||
|
ZeroDirIV bool
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ func haveDsstore(entries []fuse.DirEntry) bool {
|
|||||||
// should be a handle to the parent directory, cName is the name of the new
|
// should be a handle to the parent directory, cName is the name of the new
|
||||||
// directory and mode specifies the access permissions to use.
|
// directory and mode specifies the access permissions to use.
|
||||||
func (n *Node) mkdirWithIv(dirfd int, cName string, mode uint32, context *fuse.Context) error {
|
func (n *Node) mkdirWithIv(dirfd int, cName string, mode uint32, context *fuse.Context) error {
|
||||||
|
|
||||||
rn := n.rootNode()
|
rn := n.rootNode()
|
||||||
// Between the creation of the directory and the creation of gocryptfs.diriv
|
// Between the creation of the directory and the creation of gocryptfs.diriv
|
||||||
// the directory is inconsistent. Take the lock to prevent other readers
|
// the directory is inconsistent. Take the lock to prevent other readers
|
||||||
@ -48,7 +49,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)
|
dirfd2, err := syscallcompat.Openat(dirfd, cName, syscall.O_DIRECTORY|syscall.O_NOFOLLOW|syscallcompat.O_PATH, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Create gocryptfs.diriv
|
// Create gocryptfs.diriv
|
||||||
err = nametransform.WriteDirIVAt(dirfd2)
|
err = nametransform.WriteDirIVAt(dirfd2, !rn.args.ZeroDirIV)
|
||||||
syscall.Close(dirfd2)
|
syscall.Close(dirfd2)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package nametransform
|
package nametransform
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -34,9 +33,6 @@ func ReadDirIVAt(dirfd int) (iv []byte, err error) {
|
|||||||
return fdReadDirIV(fd)
|
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.
|
// fdReadDirIV reads and verifies the DirIV from an opened gocryptfs.diriv file.
|
||||||
func fdReadDirIV(fd *os.File) (iv []byte, err error) {
|
func fdReadDirIV(fd *os.File) (iv []byte, err error) {
|
||||||
// We want to detect if the file is bigger than DirIVLen, so
|
// We want to detect if the file is bigger than DirIVLen, so
|
||||||
@ -50,9 +46,6 @@ func fdReadDirIV(fd *os.File) (iv []byte, err error) {
|
|||||||
if len(iv) != DirIVLen {
|
if len(iv) != DirIVLen {
|
||||||
return nil, fmt.Errorf("wanted %d bytes, got %d", DirIVLen, len(iv))
|
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
|
return iv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +53,13 @@ func fdReadDirIV(fd *os.File) (iv []byte, err error) {
|
|||||||
// "dirfd". On error we try to delete the incomplete file.
|
// "dirfd". On error we try to delete the incomplete file.
|
||||||
// This function is exported because it is used from fusefrontend, main,
|
// This function is exported because it is used from fusefrontend, main,
|
||||||
// and also the automated tests.
|
// and also the automated tests.
|
||||||
func WriteDirIVAt(dirfd int) error {
|
func WriteDirIVAt(dirfd int, randomInitialization bool) error {
|
||||||
iv := cryptocore.RandBytes(DirIVLen)
|
var iv []byte
|
||||||
|
if randomInitialization {
|
||||||
|
iv = cryptocore.RandBytes(DirIVLen)
|
||||||
|
} else {
|
||||||
|
iv = make([]byte, DirIVLen)
|
||||||
|
}
|
||||||
// 0400 permissions: gocryptfs.diriv should never be modified after creation.
|
// 0400 permissions: gocryptfs.diriv should never be modified after creation.
|
||||||
// Don't use "ioutil.WriteFile", it causes trouble on NFS:
|
// Don't use "ioutil.WriteFile", it causes trouble on NFS:
|
||||||
// https://github.com/rfjakob/gocryptfs/commit/7d38f80a78644c8ec4900cc990bfb894387112ed
|
// https://github.com/rfjakob/gocryptfs/commit/7d38f80a78644c8ec4900cc990bfb894387112ed
|
||||||
|
1
mount.go
1
mount.go
@ -276,6 +276,7 @@ func initFuseFrontend(args *argContainer) (rootNode fs.InodeEmbedder, wipeKeys f
|
|||||||
KernelCache: args.kernel_cache,
|
KernelCache: args.kernel_cache,
|
||||||
SharedStorage: args.sharedstorage,
|
SharedStorage: args.sharedstorage,
|
||||||
OneFileSystem: args.one_file_system,
|
OneFileSystem: args.one_file_system,
|
||||||
|
ZeroDirIV: args.zerodiriv,
|
||||||
}
|
}
|
||||||
// confFile is nil when "-zerokey" or "-masterkey" was used
|
// confFile is nil when "-zerokey" or "-masterkey" was used
|
||||||
if confFile != nil {
|
if confFile != nil {
|
||||||
|
@ -110,7 +110,7 @@ func ResetTmpDir(createDirIV bool) {
|
|||||||
// Open cipherdir (following symlinks)
|
// Open cipherdir (following symlinks)
|
||||||
dirfd, err := syscall.Open(DefaultCipherDir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
|
dirfd, err := syscall.Open(DefaultCipherDir, syscall.O_DIRECTORY|syscallcompat.O_PATH, 0)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = nametransform.WriteDirIVAt(dirfd)
|
err = nametransform.WriteDirIVAt(dirfd, true)
|
||||||
syscall.Close(dirfd)
|
syscall.Close(dirfd)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
85
tests/zerodiriv/zerodiriv_test.go
Normal file
85
tests/zerodiriv/zerodiriv_test.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user