From ec2fdc19cf9358ae7ba09c528a5807b6b0760f9b Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Sat, 11 Aug 2018 23:26:49 +0200 Subject: [PATCH] reverse mode: add --exclude option https://github.com/rfjakob/gocryptfs/issues/235 --- Documentation/MANPAGE.md | 8 +- README.md | 1 + cli_args.go | 5 + internal/exitcodes/exitcodes.go | 2 + internal/fusefrontend/args.go | 2 + internal/fusefrontend/fs.go | 3 + internal/fusefrontend_reverse/rfile.go | 6 + internal/fusefrontend_reverse/rfs.go | 74 ++++++++++++- main.go | 5 + mount.go | 1 + tests/cli/cli_test.go | 11 ++ tests/reverse/exclude_test.go | 104 ++++++++++++++++++ .../exclude_test_fs/.gocryptfs.reverse.conf | 21 ++++ .../.gocryptfs.reverse.conf.plaintextnames | 18 +++ tests/reverse/exclude_test_fs/dir1/file1 | 0 tests/reverse/exclude_test_fs/dir1/file2 | 0 ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | 0 ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | 0 tests/reverse/exclude_test_fs/dir2/file | 0 .../file | 0 ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | 0 .../reverse/exclude_test_fs/dir2/subdir/file | 0 tests/reverse/exclude_test_fs/file1 | 0 tests/reverse/exclude_test_fs/file2 | 0 .../file | 0 .../file | 0 ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | 0 ...xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | 0 28 files changed, 258 insertions(+), 3 deletions(-) create mode 100644 tests/reverse/exclude_test.go create mode 100644 tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf create mode 100644 tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf.plaintextnames create mode 100644 tests/reverse/exclude_test_fs/dir1/file1 create mode 100644 tests/reverse/exclude_test_fs/dir1/file2 create mode 100644 tests/reverse/exclude_test_fs/dir1/longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx create mode 100644 tests/reverse/exclude_test_fs/dir1/longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx create mode 100644 tests/reverse/exclude_test_fs/dir2/file create mode 100644 tests/reverse/exclude_test_fs/dir2/longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file create mode 100644 tests/reverse/exclude_test_fs/dir2/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx create mode 100644 tests/reverse/exclude_test_fs/dir2/subdir/file create mode 100644 tests/reverse/exclude_test_fs/file1 create mode 100644 tests/reverse/exclude_test_fs/file2 create mode 100644 tests/reverse/exclude_test_fs/longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file create mode 100644 tests/reverse/exclude_test_fs/longdir2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file create mode 100644 tests/reverse/exclude_test_fs/longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx create mode 100644 tests/reverse/exclude_test_fs/longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/Documentation/MANPAGE.md b/Documentation/MANPAGE.md index a9afac0..62e0dee 100644 --- a/Documentation/MANPAGE.md +++ b/Documentation/MANPAGE.md @@ -70,12 +70,18 @@ Enable (`-dev`) or disable (`-nodev`) device files in a gocryptfs mount You need root permissions to use `-dev`. #### -devrandom -Use /dev/random for generating the master key instead of the default Go +Use `/dev/random` for generating the master key instead of the default Go implementation. This is especially useful on embedded systems with Go versions prior to 1.9, which fall back to weak random data when the getrandom syscall is blocking. Using this option can block indefinitely when the kernel cannot harvest enough entropy. +#### -exclude PATH +Only for reverse mode: exclude relative plaintext path from the encrypted +view. Can be passed multiple times. Example: + + gocryptfs -reverse -exclude Music -exclude Movies /home/user /mnt/user.encrypted + #### -exec, -noexec Enable (`-exec`) or disable (`-noexec`) executables in a gocryptfs mount (default: `-exec`). If both are specified, `-noexec` takes precedence. diff --git a/README.md b/README.md index a436fff..e8f7fea 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,7 @@ Changelog vNEXT, in progress * Fall back to buffered IO even when passed `O_DIRECT` ([commit](https://github.com/rfjakob/gocryptfs/commit/893e41149ed353f355047003b89eeff456990e76)) +* Add `-exclude` option for reverse mode v1.5, 2018-06-12 * **Support extended attributes (xattr)** in forward mode diff --git a/cli_args.go b/cli_args.go index 1314ed7..ecbfa3a 100644 --- a/cli_args.go +++ b/cli_args.go @@ -27,6 +27,8 @@ type argContainer struct { dev, nodev, suid, nosuid, exec, noexec, rw, ro bool masterkey, mountpoint, cipherdir, cpuprofile, extpass, memprofile, ko, passfile, ctlsock, fsname, force_owner, trace string + // For reverse mode, --exclude is available. It can be specified multiple times. + exclude multipleStrings // Configuration file name override config string notifypid, scryptn int @@ -173,6 +175,9 @@ func parseCliOpts() (args argContainer) { flagSet.StringVar(&args.fsname, "fsname", "", "Override the filesystem name") flagSet.StringVar(&args.force_owner, "force_owner", "", "uid:gid pair to coerce ownership") flagSet.StringVar(&args.trace, "trace", "", "Write execution trace to file") + + flagSet.Var(&args.exclude, "exclude", "Exclude relative path from reverse view") + flagSet.IntVar(&args.notifypid, "notifypid", 0, "Send USR1 to the specified process after "+ "successful mount - used internally for daemonization") flagSet.IntVar(&args.scryptn, "scryptn", configfile.ScryptDefaultLogN, "scrypt cost parameter logN. Possible values: 10-28. "+ diff --git a/internal/exitcodes/exitcodes.go b/internal/exitcodes/exitcodes.go index 3fbfdc6..b8173c7 100644 --- a/internal/exitcodes/exitcodes.go +++ b/internal/exitcodes/exitcodes.go @@ -68,6 +68,8 @@ const ( // TrezorError - an error was encountered while interacting with a Trezor // device TrezorError = 28 + // ExcludeError - an error occoured while processing "-exclude" + ExcludeError = 29 ) // Err wraps an error with an associated numeric exit code diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go index 8a64e99..5fb72cd 100644 --- a/internal/fusefrontend/args.go +++ b/internal/fusefrontend/args.go @@ -30,4 +30,6 @@ type Args struct { SerializeReads bool // Force decode even if integrity check fails (openSSL only) ForceDecode bool + // Exclude is a list of paths to make inaccessible + Exclude []string } diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index 23f5513..45b5b40 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -56,6 +56,9 @@ func NewFS(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) if args.SerializeReads { serialize_reads.InitSerializer() } + if len(args.Exclude) > 0 { + tlog.Warn.Printf("Forward mode does not support -exclude") + } return &FS{ FileSystem: pathfs.NewLoopbackFileSystem(args.Cipherdir), args: args, diff --git a/internal/fusefrontend_reverse/rfile.go b/internal/fusefrontend_reverse/rfile.go index 26756a3..7df0906 100644 --- a/internal/fusefrontend_reverse/rfile.go +++ b/internal/fusefrontend_reverse/rfile.go @@ -36,6 +36,12 @@ var inodeTable syncmap.Map // newFile decrypts and opens the path "relPath" and returns a reverseFile // object. The backing file descriptor is always read-only. func (rfs *ReverseFS) newFile(relPath string) (*reverseFile, fuse.Status) { + if rfs.isExcluded(relPath) { + // Excluded paths should have been filtered out beforehand. Better safe + // than sorry. + tlog.Warn.Printf("BUG: newFile: received excluded path %q. This should not happen.", relPath) + return nil, fuse.ENOENT + } pRelPath, err := rfs.decryptPath(relPath) if err != nil { return nil, fuse.ToStatus(err) diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go index 829983b..ba8810c 100644 --- a/internal/fusefrontend_reverse/rfs.go +++ b/internal/fusefrontend_reverse/rfs.go @@ -2,7 +2,9 @@ package fusefrontend_reverse import ( "fmt" + "os" "path/filepath" + "strings" "syscall" "golang.org/x/sys/unix" @@ -14,6 +16,8 @@ import ( "github.com/rfjakob/gocryptfs/internal/configfile" "github.com/rfjakob/gocryptfs/internal/contentenc" "github.com/rfjakob/gocryptfs/internal/cryptocore" + "github.com/rfjakob/gocryptfs/internal/ctlsock" + "github.com/rfjakob/gocryptfs/internal/exitcodes" "github.com/rfjakob/gocryptfs/internal/fusefrontend" "github.com/rfjakob/gocryptfs/internal/nametransform" "github.com/rfjakob/gocryptfs/internal/pathiv" @@ -34,6 +38,8 @@ type ReverseFS struct { nameTransform *nametransform.NameTransform // Content encryption helper contentEnc *contentenc.ContentEnc + // Relative ciphertext paths to exclude (hide) from the user. Used by -exclude. + cExclude []string } var _ pathfs.FileSystem = &ReverseFS{} @@ -43,7 +49,7 @@ var _ pathfs.FileSystem = &ReverseFS{} // ReverseFS provides an encrypted view. func NewFS(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *ReverseFS { initLongnameCache() - return &ReverseFS{ + fs := &ReverseFS{ // pathfs.defaultFileSystem returns ENOSYS for all operations FileSystem: pathfs.NewDefaultFileSystem(), loopbackfs: pathfs.NewLoopbackFileSystem(args.Cipherdir), @@ -51,6 +57,22 @@ func NewFS(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.Na nameTransform: n, contentEnc: c, } + if len(args.Exclude) > 0 { + for _, dirty := range args.Exclude { + clean := ctlsock.SanitizePath(dirty) + if clean != dirty { + tlog.Warn.Printf("-exclude: non-canonical path %q has been interpreted as %q", dirty, clean) + } + cPath, err := fs.EncryptPath(clean) + if err != nil { + tlog.Fatal.Printf("-exclude: EncryptPath %q failed: %v", clean, err) + os.Exit(exitcodes.ExcludeError) + } + fs.cExclude = append(fs.cExclude, cPath) + } + tlog.Debug.Printf("-exclude: %v -> %v", fs.args.Exclude, fs.cExclude) + } + return fs } // relDir is identical to filepath.Dir excepts that it returns "" when @@ -64,6 +86,21 @@ func relDir(path string) string { return dir } +// isExcluded finds out if relative ciphertext path "relPath" is excluded +// (used when -exclude is passed by the user) +func (rfs *ReverseFS) isExcluded(relPath string) bool { + for _, e := range rfs.cExclude { + if e == relPath { + return true + } + // Files inside an excluded directory are also excluded + if strings.HasPrefix(relPath, e+"/") { + return true + } + } + return false +} + // isDirIV determines if the path points to a gocryptfs.diriv file func (rfs *ReverseFS) isDirIV(relPath string) bool { if rfs.args.PlaintextNames { @@ -99,6 +136,9 @@ func (rfs *ReverseFS) isTranslatedConfig(relPath string) bool { // GetAttr - FUSE call // "relPath" is the relative ciphertext path func (rfs *ReverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.Status) { + if rfs.isExcluded(relPath) { + return nil, fuse.ENOENT + } // Handle "gocryptfs.conf" if rfs.isTranslatedConfig(relPath) { absConfPath, _ := rfs.abs(configfile.ConfReverseName, nil) @@ -180,6 +220,9 @@ func (rfs *ReverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr // Access - FUSE call func (rfs *ReverseFS) Access(relPath string, mode uint32, context *fuse.Context) fuse.Status { + if rfs.isExcluded(relPath) { + return fuse.ENOENT + } if rfs.isTranslatedConfig(relPath) || rfs.isDirIV(relPath) || rfs.isNameFile(relPath) { // access(2) R_OK flag for checking if the file is readable, always 4 as defined in POSIX. ROK := uint32(0x4) @@ -203,6 +246,9 @@ func (rfs *ReverseFS) Access(relPath string, mode uint32, context *fuse.Context) // Open - FUSE call func (rfs *ReverseFS) Open(relPath string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) { + if rfs.isExcluded(relPath) { + return nil, fuse.ENOENT + } if rfs.isTranslatedConfig(relPath) { return rfs.loopbackfs.Open(configfile.ConfReverseName, flags, context) } @@ -242,6 +288,9 @@ func (rfs *ReverseFS) openDirPlaintextnames(relPath string, entries []fuse.DirEn // OpenDir - FUSE readdir call func (rfs *ReverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) { + if rfs.isExcluded(cipherPath) { + return nil, fuse.ENOENT + } relPath, err := rfs.decryptPath(cipherPath) if err != nil { return nil, fuse.ToStatus(err) @@ -292,6 +341,21 @@ func (rfs *ReverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse. } entries[i].Name = cName } + // Filter out excluded entries + if rfs.cExclude != nil { + filtered := make([]fuse.DirEntry, 0, len(entries)) + for _, entry := range entries { + // filepath.Join handles the case of cipherPath="" correctly: + // Join("", "foo") -> "foo". This does not: cipherPath + "/" + name" + p := filepath.Join(cipherPath, entry.Name) + if rfs.isExcluded(p) { + // Skip file + continue + } + filtered = append(filtered, entry) + } + entries = filtered + } entries = append(entries, virtualFiles[:nVirtual]...) return entries, fuse.OK } @@ -301,7 +365,10 @@ func (rfs *ReverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse. // Securing statfs against symlink races seems to be more trouble than // it's worth, so we just ignore the path and always return info about the // backing storage root dir. -func (rfs *ReverseFS) StatFs(path string) *fuse.StatfsOut { +func (rfs *ReverseFS) StatFs(relPath string) *fuse.StatfsOut { + if rfs.isExcluded(relPath) { + return nil + } var s syscall.Statfs_t err := syscall.Statfs(rfs.args.Cipherdir, &s) if err != nil { @@ -314,6 +381,9 @@ func (rfs *ReverseFS) StatFs(path string) *fuse.StatfsOut { // Readlink - FUSE call func (rfs *ReverseFS) Readlink(relPath string, context *fuse.Context) (string, fuse.Status) { + if rfs.isExcluded(relPath) { + return "", fuse.ENOENT + } dirfd, name, err := rfs.openBackingDir(relPath) if err != nil { return "", fuse.ToStatus(err) diff --git a/main.go b/main.go index 24f16bd..f423cd1 100644 --- a/main.go +++ b/main.go @@ -212,6 +212,11 @@ func main() { // "-reverse" implies "-aessiv" if args.reverse { args.aessiv = true + } else { + if args.exclude != nil { + tlog.Fatal.Printf("-exclude only works in reverse mode") + os.Exit(exitcodes.ExcludeError) + } } // "-config" if args.config != "" { diff --git a/mount.go b/mount.go index a673848..e9714d4 100644 --- a/mount.go +++ b/mount.go @@ -196,6 +196,7 @@ func initFuseFrontend(args *argContainer) (pfs pathfs.FileSystem, wipeKeys func( SerializeReads: args.serialize_reads, ForceDecode: args.forcedecode, ForceOwner: args._forceOwner, + Exclude: args.exclude, } // confFile is nil when "-zerokey" or "-masterkey" was used if confFile != nil { diff --git a/tests/cli/cli_test.go b/tests/cli/cli_test.go index 5b78359..3b53181 100644 --- a/tests/cli/cli_test.go +++ b/tests/cli/cli_test.go @@ -484,3 +484,14 @@ func TestMissingOArg(t *testing.T) { exitcodes.Usage, exitCode) } } + +// -exclude must return an error in forward mode +func TestExcludeForward(t *testing.T) { + dir := test_helpers.InitFS(t) + mnt := dir + ".mnt" + err := test_helpers.Mount(dir, mnt, false, "-extpass", "echo test", "-exclude", "foo") + if err == nil { + t.Errorf("-exclude in forward mode should fail") + } + t.Log(err) +} diff --git a/tests/reverse/exclude_test.go b/tests/reverse/exclude_test.go new file mode 100644 index 0000000..a64b3da --- /dev/null +++ b/tests/reverse/exclude_test.go @@ -0,0 +1,104 @@ +package reverse_test + +import ( + "io/ioutil" + "testing" + + "github.com/rfjakob/gocryptfs/internal/ctlsock" + "github.com/rfjakob/gocryptfs/tests/test_helpers" +) + +const xxx = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +/* +tree exclude_test_fs +exclude_test_fs/ +├── dir1 +│ ├── file1 +│ ├── file2 +│ ├── longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +│ └── longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +├── dir2 +│ ├── file +│ ├── longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +│ │ └── file +│ ├── longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +│ └── subdir +│ └── file +├── file1 +├── file2 +├── longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +│ └── file +├── longdir2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +│ └── file +├── longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +└── longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +*/ + +func ctlsockEncryptPath(t *testing.T, sock string, path string) string { + req := ctlsock.RequestStruct{EncryptPath: path} + response := test_helpers.QueryCtlSock(t, sock, req) + if response.ErrNo != 0 { + t.Fatal(response) + } + return response.Result +} + +func TestExclude(t *testing.T) { + pOk := []string{ + "file2", + "dir1/file1", + "dir1/longfile1" + xxx, + "longdir1" + xxx, + "longdir1" + xxx + "/file", + "longfile1" + xxx, + } + pExclude := []string{ + "file1", + "dir1/file2", + "dir1/longfile2" + xxx, + "dir2", + "dir2/file", + "dir2/file/xxx", + "dir2/subdir", + "dir2/subdir/file", + "dir2/longdir1" + xxx + "/file", + "dir2/longfile." + xxx, + "longfile2" + xxx, + } + // Mount reverse fs + mnt, err := ioutil.TempDir(test_helpers.TmpDir, "TestExclude") + if err != nil { + t.Fatal(err) + } + sock := mnt + ".sock" + cliArgs := []string{"-reverse", "-extpass", "echo test", "-ctlsock", sock} + for _, v := range pExclude { + cliArgs = append(cliArgs, "-exclude", v) + } + if plaintextnames { + cliArgs = append(cliArgs, "-config", "exclude_test_fs/.gocryptfs.reverse.conf.plaintextnames") + } + test_helpers.MountOrFatal(t, "exclude_test_fs", mnt, cliArgs...) + defer test_helpers.UnmountPanic(mnt) + // Get encrypted version of "ok" and "excluded" paths + cOk := make([]string, len(pOk)) + cExclude := make([]string, len(pExclude)) + for i, v := range pOk { + cOk[i] = ctlsockEncryptPath(t, sock, v) + } + for i, v := range pExclude { + cExclude[i] = ctlsockEncryptPath(t, sock, v) + } + // Check that "excluded" paths are not there and "ok" paths are there + for i, v := range cExclude { + if test_helpers.VerifyExistence(mnt + "/" + v) { + t.Errorf("File %q / %q is visible, but should be excluded", pExclude[i], v) + } + } + for i, v := range cOk { + if !test_helpers.VerifyExistence(mnt + "/" + v) { + t.Errorf("File %q / %q is hidden, but should be visible", pOk[i], v) + } + } +} diff --git a/tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf b/tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf new file mode 100644 index 0000000..835d11c --- /dev/null +++ b/tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf @@ -0,0 +1,21 @@ +{ + "Creator": "gocryptfs v1.5-41-gf48b731-dirty", + "EncryptedKey": "FkACqloUeFZesem0UzRD3ezLXtPl8wIAxEHoIEfZxFdLMQeWOxqtw5xopJagDWE/GI1VFSUIrJIIIwwgMipmYA==", + "ScryptObject": { + "Salt": "UVfIgV31uj/voHWI4GqGwsTcbVKyYDOWvbleqJKhZbk=", + "N": 1024, + "R": 8, + "P": 1, + "KeyLen": 32 + }, + "Version": 2, + "FeatureFlags": [ + "GCMIV128", + "HKDF", + "DirIV", + "EMENames", + "LongNames", + "Raw64", + "AESSIV" + ] +} diff --git a/tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf.plaintextnames b/tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf.plaintextnames new file mode 100644 index 0000000..9cb762c --- /dev/null +++ b/tests/reverse/exclude_test_fs/.gocryptfs.reverse.conf.plaintextnames @@ -0,0 +1,18 @@ +{ + "Creator": "gocryptfs v1.5-41-gf48b731-dirty", + "EncryptedKey": "wAmckZb7QsIv/GCdkhb5ep8TwJa44qhnswn5tbER6Tifk8TbUmkwBTceaTtYfHAnTQ48q9mnIlcN9cfbNe5oPw==", + "ScryptObject": { + "Salt": "o5XJ78TgG85zZXRnU55ZqHhKLbPge6jsyDiqrLvSqe0=", + "N": 1024, + "R": 8, + "P": 1, + "KeyLen": 32 + }, + "Version": 2, + "FeatureFlags": [ + "GCMIV128", + "HKDF", + "PlaintextNames", + "AESSIV" + ] +} diff --git a/tests/reverse/exclude_test_fs/dir1/file1 b/tests/reverse/exclude_test_fs/dir1/file1 new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/dir1/file2 b/tests/reverse/exclude_test_fs/dir1/file2 new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/dir1/longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx b/tests/reverse/exclude_test_fs/dir1/longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/dir1/longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx b/tests/reverse/exclude_test_fs/dir1/longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/dir2/file b/tests/reverse/exclude_test_fs/dir2/file new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/dir2/longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file b/tests/reverse/exclude_test_fs/dir2/longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/dir2/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx b/tests/reverse/exclude_test_fs/dir2/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/dir2/subdir/file b/tests/reverse/exclude_test_fs/dir2/subdir/file new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/file1 b/tests/reverse/exclude_test_fs/file1 new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/file2 b/tests/reverse/exclude_test_fs/file2 new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file b/tests/reverse/exclude_test_fs/longdir1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/longdir2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file b/tests/reverse/exclude_test_fs/longdir2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx b/tests/reverse/exclude_test_fs/longfile1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx new file mode 100644 index 0000000..e69de29 diff --git a/tests/reverse/exclude_test_fs/longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx b/tests/reverse/exclude_test_fs/longfile2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx new file mode 100644 index 0000000..e69de29