summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-10-08 20:57:38 +0200
committerJakob Unterwurzacher2016-10-08 20:57:38 +0200
commitf054353bd3b05ab0d3d024ec8fa809bc5fed1d08 (patch)
treed5dfcccc3035e552449c4796207920fd4f1275e4
parentdde4a66454107709a7309ca5047ceb0ecf3c0b9f (diff)
reverse: make gocryptfs.conf mapping plaintextnames-aware
Only in plaintextnames-mode AND with the config file at the default location it will be mapped into the mountpoint. Also adds a test for that.
-rw-r--r--cli_args.go3
-rw-r--r--internal/fusefrontend/args.go4
-rw-r--r--internal/fusefrontend_reverse/rfs.go53
-rw-r--r--main.go1
-rw-r--r--mount.go1
-rw-r--r--tests/reverse/correctness_test.go15
-rw-r--r--tests/reverse/main_test.go46
7 files changed, 95 insertions, 28 deletions
diff --git a/cli_args.go b/cli_args.go
index dd570d3..d80e937 100644
--- a/cli_args.go
+++ b/cli_args.go
@@ -20,6 +20,9 @@ type argContainer struct {
// Configuration file name override
config string
notifypid, scryptn int
+ // _configCustom is true when the user sets a custom config file name.
+ // This is not a CLI option.
+ _configCustom bool
}
var flagSet *flag.FlagSet
diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go
index 64ca899..204647d 100644
--- a/internal/fusefrontend/args.go
+++ b/internal/fusefrontend/args.go
@@ -14,4 +14,8 @@ type Args struct {
// Should we chown a file after it has been created?
// This only makes sense if (1) allow_other is set and (2) we run as root.
PreserveOwner bool
+ // ConfigCustom is true when the user select a non-default config file
+ // location. If it is false, reverse mode maps ".gocryptfs.reverse.conf"
+ // to "gocryptfs.conf" in the plaintext dir.
+ ConfigCustom bool
}
diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go
index 1c143bf..36f49be 100644
--- a/internal/fusefrontend_reverse/rfs.go
+++ b/internal/fusefrontend_reverse/rfs.go
@@ -17,6 +17,7 @@ import (
"github.com/rfjakob/gocryptfs/internal/cryptocore"
"github.com/rfjakob/gocryptfs/internal/fusefrontend"
"github.com/rfjakob/gocryptfs/internal/nametransform"
+ "github.com/rfjakob/gocryptfs/internal/tlog"
)
const (
@@ -110,13 +111,19 @@ func (rfs *reverseFS) dirIVAttr(relPath string, context *fuse.Context) (*fuse.At
}
// isDirIV determines if the path points to a gocryptfs.diriv file
-func isDirIV(relPath string) bool {
+func (rfs *reverseFS) isDirIV(relPath string) bool {
+ if rfs.args.PlaintextNames {
+ return false
+ }
return filepath.Base(relPath) == nametransform.DirIVFilename
}
// isNameFile determines if the path points to a gocryptfs.longname.*.name
// file
-func isNameFile(relPath string) bool {
+func (rfs *reverseFS) isNameFile(relPath string) bool {
+ if rfs.args.PlaintextNames {
+ return false
+ }
fileType := nametransform.NameType(filepath.Base(relPath))
return fileType == nametransform.LongNameFilename
}
@@ -161,19 +168,15 @@ func (rfs *reverseFS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr
if relPath == configfile.ConfDefaultName {
return rfs.inoAwareStat(configfile.ConfReverseName)
}
- if rfs.isFiltered(relPath) {
- return nil, fuse.EPERM
- }
-
// Handle virtual files
var f nodefs.File
var status fuse.Status
virtual := false
- if isDirIV(relPath) {
+ if rfs.isDirIV(relPath) {
virtual = true
f, status = rfs.newDirIVFile(relPath)
}
- if isNameFile(relPath) {
+ if rfs.isNameFile(relPath) {
virtual = true
f, status = rfs.newNameFile(relPath)
}
@@ -204,7 +207,7 @@ 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 isDirIV(relPath) {
+ if rfs.isDirIV(relPath) {
return fuse.OK
}
if rfs.isFiltered(relPath) {
@@ -223,10 +226,10 @@ func (rfs *reverseFS) Open(relPath string, flags uint32, context *fuse.Context)
// gocryptfs.conf maps to .gocryptfs.reverse.conf in the plaintext directory
return rfs.loopbackfs.Open(configfile.ConfReverseName, flags, context)
}
- if isDirIV(relPath) {
+ if rfs.isDirIV(relPath) {
return rfs.newDirIVFile(relPath)
}
- if isNameFile(relPath) {
+ if rfs.isNameFile(relPath) {
return rfs.newNameFile(relPath)
}
if rfs.isFiltered(relPath) {
@@ -235,6 +238,31 @@ func (rfs *reverseFS) Open(relPath string, flags uint32, context *fuse.Context)
return rfs.NewFile(relPath, flags)
}
+func (rfs *reverseFS) openDirPlaintextnames(relPath string, entries []fuse.DirEntry) ([]fuse.DirEntry, fuse.Status) {
+ if relPath != "" || rfs.args.ConfigCustom {
+ return entries, fuse.OK
+ }
+ // We are in the root dir and the default config file name
+ // ".gocryptfs.reverse.conf" is used. We map it to "gocryptfs.conf".
+ dupe := -1
+ status := fuse.OK
+ for i := range entries {
+ if entries[i].Name == configfile.ConfReverseName {
+ entries[i].Name = configfile.ConfDefaultName
+ } else if entries[i].Name == configfile.ConfDefaultName {
+ dupe = i
+ }
+ }
+ if dupe >= 0 {
+ // Warn the user loudly: The gocryptfs.conf_NAME_COLLISION file will
+ // throw ENOENT errors that are hard to miss.
+ tlog.Warn.Printf("The file %s is mapped to %s and shadows another file. Please rename %s in %s .",
+ configfile.ConfReverseName, configfile.ConfDefaultName, configfile.ConfDefaultName, rfs.args.Cipherdir)
+ entries[dupe].Name = "gocryptfs.conf_NAME_COLLISION_" + fmt.Sprintf("%d", cryptocore.RandUint64())
+ }
+ return entries, status
+}
+
// OpenDir - FUSE readdir call
func (rfs *reverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) {
relPath, err := rfs.decryptPath(cipherPath)
@@ -246,6 +274,9 @@ func (rfs *reverseFS) OpenDir(cipherPath string, context *fuse.Context) ([]fuse.
if entries == nil {
return nil, status
}
+ if rfs.args.PlaintextNames {
+ return rfs.openDirPlaintextnames(cipherPath, entries)
+ }
// Allocate maximum possible number of virtual files.
// If all files have long names we need a virtual ".name" file for each,
// plus one for gocryptfs.diriv.
diff --git a/main.go b/main.go
index 467a143..5ae8146 100644
--- a/main.go
+++ b/main.go
@@ -155,6 +155,7 @@ func main() {
os.Exit(ErrExitInit)
}
tlog.Info.Printf("Using config file at custom location %s", args.config)
+ args._configCustom = true
} else if args.reverse {
args.config = filepath.Join(args.cipherdir, configfile.ConfReverseName)
} else {
diff --git a/mount.go b/mount.go
index 90443ff..000d632 100644
--- a/mount.go
+++ b/mount.go
@@ -125,6 +125,7 @@ func initFuseFrontend(key []byte, args *argContainer, confFile *configfile.ConfF
PlaintextNames: args.plaintextnames,
LongNames: args.longnames,
CryptoBackend: cryptoBackend,
+ ConfigCustom: args._configCustom,
}
// confFile is nil when "-zerokey" or "-masterkey" was used
if confFile != nil {
diff --git a/tests/reverse/correctness_test.go b/tests/reverse/correctness_test.go
index 40bd320..c75a1fd 100644
--- a/tests/reverse/correctness_test.go
+++ b/tests/reverse/correctness_test.go
@@ -1,6 +1,7 @@
package reverse_test
import (
+ "io/ioutil"
"os"
"testing"
//"time"
@@ -49,3 +50,17 @@ func TestSymlinks(t *testing.T) {
t.Errorf("wrong symlink target: want=%q have=%q", target, actualTarget)
}
}
+
+// .gocryptfs.reverse.conf in the plaintext dir should be visible as
+// gocryptfs.conf
+func TestConfigMapping(t *testing.T) {
+ c := dirB + "/gocryptfs.conf"
+ test_helpers.VerifyExistence(c)
+ data, err := ioutil.ReadFile(c)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(data) == 0 {
+ t.Errorf("empty file")
+ }
+}
diff --git a/tests/reverse/main_test.go b/tests/reverse/main_test.go
index a42bb82..a2b7eb6 100644
--- a/tests/reverse/main_test.go
+++ b/tests/reverse/main_test.go
@@ -10,26 +10,38 @@ import (
var dirA, dirB, dirC string
var x240 string
+var plaintextnames bool
func TestMain(m *testing.M) {
x240 = string(bytes.Repeat([]byte("x"), 240))
- dirA = test_helpers.TmpDir + "/a"
- dirB = test_helpers.TmpDir + "/b"
- dirC = test_helpers.TmpDir + "/c"
- if err := os.Mkdir(dirA, 0700); err != nil {
- panic(err)
- }
- if err := os.Mkdir(dirB, 0700); err != nil {
- panic(err)
- }
- if err := os.Mkdir(dirC, 0700); err != nil {
- panic(err)
+ var r int
+ for _, plaintextnames = range []bool{false, true} {
+ argsA := []string{"-reverse"}
+ if plaintextnames {
+ argsA = append(argsA, "-plaintextnames")
+ }
+ dirA = test_helpers.InitFS(nil, argsA...)
+ dirB = test_helpers.TmpDir + "/b"
+ dirC = test_helpers.TmpDir + "/c"
+ if err := os.Mkdir(dirB, 0700); err != nil {
+ panic(err)
+ }
+ if err := os.Mkdir(dirC, 0700); err != nil {
+ panic(err)
+ }
+ test_helpers.MountOrExit(dirA, dirB, "-reverse", "-extpass", "echo test")
+ test_helpers.MountOrExit(dirB, dirC, "-extpass", "echo test")
+ r = m.Run()
+ test_helpers.UnmountPanic(dirC)
+ test_helpers.UnmountPanic(dirB)
+
+ os.RemoveAll(dirA)
+ os.RemoveAll(dirB)
+ os.RemoveAll(dirC)
+
+ if r != 0 {
+ os.Exit(r)
+ }
}
- test_helpers.MountOrExit(dirA, dirB, "-zerokey", "-reverse")
- test_helpers.MountOrExit(dirB, dirC, "-zerokey", "-aessiv")
- r := m.Run()
- test_helpers.UnmountPanic(dirC)
- test_helpers.UnmountPanic(dirB)
- os.RemoveAll(test_helpers.TmpDir)
os.Exit(r)
}