diff --git a/internal/fusefrontend/args.go b/internal/fusefrontend/args.go index fc9de73..8a64e99 100644 --- a/internal/fusefrontend/args.go +++ b/internal/fusefrontend/args.go @@ -2,7 +2,6 @@ package fusefrontend import ( "github.com/hanwen/go-fuse/fuse" - "github.com/rfjakob/gocryptfs/internal/cryptocore" ) // Args is a container for arguments that are passed from main() to fusefrontend @@ -10,7 +9,6 @@ type Args struct { // Cipherdir is the backing storage directory (absolute path). // For reverse mode, Cipherdir actually contains *plaintext* files. Cipherdir string - CryptoBackend cryptocore.AEADTypeEnum PlaintextNames bool LongNames bool // Should we chown a file after it has been created? @@ -26,15 +24,8 @@ type Args struct { // location. If it is false, reverse mode maps ".gocryptfs.reverse.conf" // to "gocryptfs.conf" in the plaintext dir. ConfigCustom bool - // Raw64 is true when RawURLEncoding (without padding) should be used for - // file names. - // Corresponds to the Raw64 feature flag introduced in gocryptfs v1.2. - Raw64 bool // NoPrealloc disables automatic preallocation before writing NoPrealloc bool - // Use HKDF key derivation. - // Corresponds to the HKDF feature flag introduced in gocryptfs v1.3. - HKDF bool // Try to serialize read operations, "-serialize_reads" SerializeReads bool // Force decode even if integrity check fails (openSSL only) diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go index 8b0bb2e..b09ed83 100644 --- a/internal/fusefrontend/fs.go +++ b/internal/fusefrontend/fs.go @@ -17,7 +17,6 @@ import ( "github.com/hanwen/go-fuse/fuse/pathfs" "github.com/rfjakob/gocryptfs/internal/contentenc" - "github.com/rfjakob/gocryptfs/internal/cryptocore" "github.com/rfjakob/gocryptfs/internal/nametransform" "github.com/rfjakob/gocryptfs/internal/serialize_reads" "github.com/rfjakob/gocryptfs/internal/syscallcompat" @@ -44,20 +43,15 @@ type FS struct { var _ pathfs.FileSystem = &FS{} // Verify that interface is implemented. // NewFS returns a new encrypted FUSE overlay filesystem. -func NewFS(masterkey []byte, args Args) *FS { - cryptoCore := cryptocore.New(masterkey, args.CryptoBackend, contentenc.DefaultIVBits, args.HKDF, args.ForceDecode) - contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS, args.ForceDecode) - nameTransform := nametransform.New(cryptoCore.EMECipher, args.LongNames, args.Raw64) - +func NewFS(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *FS { if args.SerializeReads { serialize_reads.InitSerializer() } - return &FS{ FileSystem: pathfs.NewLoopbackFileSystem(args.Cipherdir), args: args, - nameTransform: nameTransform, - contentEnc: contentEnc, + nameTransform: n, + contentEnc: c, } } diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go index 1523c18..b281c76 100644 --- a/internal/fusefrontend_reverse/rfs.go +++ b/internal/fusefrontend_reverse/rfs.go @@ -2,7 +2,6 @@ package fusefrontend_reverse import ( "fmt" - "log" "path/filepath" "syscall" @@ -42,22 +41,15 @@ var _ pathfs.FileSystem = &ReverseFS{} // NewFS returns an encrypted FUSE overlay filesystem. // In this case (reverse mode) the backing directory is plain-text and // ReverseFS provides an encrypted view. -func NewFS(masterkey []byte, args fusefrontend.Args) *ReverseFS { - if args.CryptoBackend != cryptocore.BackendAESSIV { - log.Panic("reverse mode must use AES-SIV, everything else is insecure") - } +func NewFS(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *ReverseFS { initLongnameCache() - cryptoCore := cryptocore.New(masterkey, args.CryptoBackend, contentenc.DefaultIVBits, args.HKDF, false) - contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS, false) - nameTransform := nametransform.New(cryptoCore.EMECipher, args.LongNames, args.Raw64) - return &ReverseFS{ // pathfs.defaultFileSystem returns ENOSYS for all operations FileSystem: pathfs.NewDefaultFileSystem(), loopbackfs: pathfs.NewLoopbackFileSystem(args.Cipherdir), args: args, - nameTransform: nameTransform, - contentEnc: contentEnc, + nameTransform: n, + contentEnc: c, } } diff --git a/mount.go b/mount.go index 8a23a52..7b1fd4e 100644 --- a/mount.go +++ b/mount.go @@ -3,6 +3,7 @@ package main import ( "encoding/json" "fmt" + "log" "log/syslog" "net" "os" @@ -21,11 +22,13 @@ import ( "github.com/hanwen/go-fuse/fuse/pathfs" "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/fusefrontend_reverse" + "github.com/rfjakob/gocryptfs/internal/nametransform" "github.com/rfjakob/gocryptfs/internal/readpassword" "github.com/rfjakob/gocryptfs/internal/tlog" ) @@ -182,6 +185,13 @@ func setOpenFileLimit() { } } +// ctlsockFs satisfies both the pathfs.FileSystem and the ctlsock.Interface +// interfaces +type ctlsockFs interface { + pathfs.FileSystem + ctlsock.Interface +} + // initFuseFrontend - initialize gocryptfs/fusefrontend // Calls os.Exit on errors func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile.ConfFile) *fuse.Server { @@ -203,11 +213,8 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile Cipherdir: args.cipherdir, PlaintextNames: args.plaintextnames, LongNames: args.longnames, - CryptoBackend: cryptoBackend, ConfigCustom: args._configCustom, - Raw64: args.raw64, NoPrealloc: args.noprealloc, - HKDF: args.hkdf, SerializeReads: args.serialize_reads, ForceDecode: args.forcedecode, ForceOwner: args._forceOwner, @@ -216,10 +223,10 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile if confFile != nil { // Settings from the config file override command line args frontendArgs.PlaintextNames = confFile.IsFeatureFlagSet(configfile.FlagPlaintextNames) - frontendArgs.Raw64 = confFile.IsFeatureFlagSet(configfile.FlagRaw64) - frontendArgs.HKDF = confFile.IsFeatureFlagSet(configfile.FlagHKDF) + args.raw64 = confFile.IsFeatureFlagSet(configfile.FlagRaw64) + args.hkdf = confFile.IsFeatureFlagSet(configfile.FlagHKDF) if confFile.IsFeatureFlagSet(configfile.FlagAESSIV) { - frontendArgs.CryptoBackend = cryptocore.BackendAESSIV + cryptoBackend = cryptocore.BackendAESSIV } else if args.reverse { tlog.Fatal.Printf("AES-SIV is required by reverse mode, but not enabled in the config file") os.Exit(exitcodes.Usage) @@ -232,8 +239,6 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile } jsonBytes, _ := json.MarshalIndent(frontendArgs, "", "\t") tlog.Debug.Printf("frontendArgs: %s", string(jsonBytes)) - var finalFs pathfs.FileSystem - var ctlSockBackend ctlsock.Interface // pathFsOpts are passed into go-fuse/pathfs pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true} if args.sharedstorage { @@ -242,21 +247,23 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile // https://github.com/rfjakob/gocryptfs/issues/156 pathFsOpts.ClientInodes = false } + // 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) + // Spawn fusefrontend + var fs ctlsockFs if args.reverse { - // The dance with the intermediate variables is because we need to - // cast the FS into pathfs.FileSystem *and* ctlsock.Interface. This - // avoids using interface{}. - fs := fusefrontend_reverse.NewFS(masterkey, frontendArgs) - finalFs = fs - ctlSockBackend = fs + if cryptoBackend != cryptocore.BackendAESSIV { + log.Panic("reverse mode must use AES-SIV, everything else is insecure") + } + fs = fusefrontend_reverse.NewFS(frontendArgs, cEnc, nameTransform) // Reverse mode is read-only, so we don't need a working link(). // Disable hard link tracking to avoid strange breakage on duplicate // inode numbers ( https://github.com/rfjakob/gocryptfs/issues/149 ). pathFsOpts.ClientInodes = false } else { - fs := fusefrontend.NewFS(masterkey, frontendArgs) - finalFs = fs - ctlSockBackend = fs + fs = fusefrontend.NewFS(frontendArgs, cEnc, nameTransform) } // fusefrontend / fusefrontend_reverse have initialized their crypto with // derived keys (HKDF), we can purge the master key from memory. @@ -266,9 +273,9 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile // We have opened the socket early so that we cannot fail here after // asking the user for the password if args._ctlsockFd != nil { - go ctlsock.Serve(args._ctlsockFd, ctlSockBackend) + go ctlsock.Serve(args._ctlsockFd, fs) } - pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts) + pathFs := pathfs.NewPathNodeFs(fs, pathFsOpts) var fuseOpts *nodefs.Options if args.sharedstorage { // sharedstorage mode sets all cache timeouts to zero so changes to the