fusefrontend[_reverse]: move crypto init up to caller
Both fusefrontend and fusefrontend_reverse were doing essentially the same thing, move it into main's initFuseFrontend. A side-effect is that we have a reference to cryptocore in main, which will help with wiping the keys on exit (https://github.com/rfjakob/gocryptfs/issues/211).
This commit is contained in:
parent
eeed4b4bef
commit
719693ec5d
|
@ -2,7 +2,6 @@ package fusefrontend
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hanwen/go-fuse/fuse"
|
"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
|
// 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).
|
// Cipherdir is the backing storage directory (absolute path).
|
||||||
// For reverse mode, Cipherdir actually contains *plaintext* files.
|
// For reverse mode, Cipherdir actually contains *plaintext* files.
|
||||||
Cipherdir string
|
Cipherdir string
|
||||||
CryptoBackend cryptocore.AEADTypeEnum
|
|
||||||
PlaintextNames bool
|
PlaintextNames bool
|
||||||
LongNames bool
|
LongNames bool
|
||||||
// Should we chown a file after it has been created?
|
// 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"
|
// location. If it is false, reverse mode maps ".gocryptfs.reverse.conf"
|
||||||
// to "gocryptfs.conf" in the plaintext dir.
|
// to "gocryptfs.conf" in the plaintext dir.
|
||||||
ConfigCustom bool
|
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 disables automatic preallocation before writing
|
||||||
NoPrealloc bool
|
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"
|
// Try to serialize read operations, "-serialize_reads"
|
||||||
SerializeReads bool
|
SerializeReads bool
|
||||||
// Force decode even if integrity check fails (openSSL only)
|
// Force decode even if integrity check fails (openSSL only)
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"github.com/hanwen/go-fuse/fuse/pathfs"
|
"github.com/hanwen/go-fuse/fuse/pathfs"
|
||||||
|
|
||||||
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
||||||
"github.com/rfjakob/gocryptfs/internal/cryptocore"
|
|
||||||
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
||||||
"github.com/rfjakob/gocryptfs/internal/serialize_reads"
|
"github.com/rfjakob/gocryptfs/internal/serialize_reads"
|
||||||
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
"github.com/rfjakob/gocryptfs/internal/syscallcompat"
|
||||||
|
@ -44,20 +43,15 @@ type FS struct {
|
||||||
var _ pathfs.FileSystem = &FS{} // Verify that interface is implemented.
|
var _ pathfs.FileSystem = &FS{} // Verify that interface is implemented.
|
||||||
|
|
||||||
// NewFS returns a new encrypted FUSE overlay filesystem.
|
// NewFS returns a new encrypted FUSE overlay filesystem.
|
||||||
func NewFS(masterkey []byte, args Args) *FS {
|
func NewFS(args Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *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)
|
|
||||||
|
|
||||||
if args.SerializeReads {
|
if args.SerializeReads {
|
||||||
serialize_reads.InitSerializer()
|
serialize_reads.InitSerializer()
|
||||||
}
|
}
|
||||||
|
|
||||||
return &FS{
|
return &FS{
|
||||||
FileSystem: pathfs.NewLoopbackFileSystem(args.Cipherdir),
|
FileSystem: pathfs.NewLoopbackFileSystem(args.Cipherdir),
|
||||||
args: args,
|
args: args,
|
||||||
nameTransform: nameTransform,
|
nameTransform: n,
|
||||||
contentEnc: contentEnc,
|
contentEnc: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package fusefrontend_reverse
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
@ -42,22 +41,15 @@ var _ pathfs.FileSystem = &ReverseFS{}
|
||||||
// NewFS returns an encrypted FUSE overlay filesystem.
|
// NewFS returns an encrypted FUSE overlay filesystem.
|
||||||
// In this case (reverse mode) the backing directory is plain-text and
|
// In this case (reverse mode) the backing directory is plain-text and
|
||||||
// ReverseFS provides an encrypted view.
|
// ReverseFS provides an encrypted view.
|
||||||
func NewFS(masterkey []byte, args fusefrontend.Args) *ReverseFS {
|
func NewFS(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransform.NameTransform) *ReverseFS {
|
||||||
if args.CryptoBackend != cryptocore.BackendAESSIV {
|
|
||||||
log.Panic("reverse mode must use AES-SIV, everything else is insecure")
|
|
||||||
}
|
|
||||||
initLongnameCache()
|
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{
|
return &ReverseFS{
|
||||||
// pathfs.defaultFileSystem returns ENOSYS for all operations
|
// pathfs.defaultFileSystem returns ENOSYS for all operations
|
||||||
FileSystem: pathfs.NewDefaultFileSystem(),
|
FileSystem: pathfs.NewDefaultFileSystem(),
|
||||||
loopbackfs: pathfs.NewLoopbackFileSystem(args.Cipherdir),
|
loopbackfs: pathfs.NewLoopbackFileSystem(args.Cipherdir),
|
||||||
args: args,
|
args: args,
|
||||||
nameTransform: nameTransform,
|
nameTransform: n,
|
||||||
contentEnc: contentEnc,
|
contentEnc: c,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
45
mount.go
45
mount.go
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
@ -21,11 +22,13 @@ import (
|
||||||
"github.com/hanwen/go-fuse/fuse/pathfs"
|
"github.com/hanwen/go-fuse/fuse/pathfs"
|
||||||
|
|
||||||
"github.com/rfjakob/gocryptfs/internal/configfile"
|
"github.com/rfjakob/gocryptfs/internal/configfile"
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/contentenc"
|
||||||
"github.com/rfjakob/gocryptfs/internal/cryptocore"
|
"github.com/rfjakob/gocryptfs/internal/cryptocore"
|
||||||
"github.com/rfjakob/gocryptfs/internal/ctlsock"
|
"github.com/rfjakob/gocryptfs/internal/ctlsock"
|
||||||
"github.com/rfjakob/gocryptfs/internal/exitcodes"
|
"github.com/rfjakob/gocryptfs/internal/exitcodes"
|
||||||
"github.com/rfjakob/gocryptfs/internal/fusefrontend"
|
"github.com/rfjakob/gocryptfs/internal/fusefrontend"
|
||||||
"github.com/rfjakob/gocryptfs/internal/fusefrontend_reverse"
|
"github.com/rfjakob/gocryptfs/internal/fusefrontend_reverse"
|
||||||
|
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
||||||
"github.com/rfjakob/gocryptfs/internal/readpassword"
|
"github.com/rfjakob/gocryptfs/internal/readpassword"
|
||||||
"github.com/rfjakob/gocryptfs/internal/tlog"
|
"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
|
// initFuseFrontend - initialize gocryptfs/fusefrontend
|
||||||
// Calls os.Exit on errors
|
// Calls os.Exit on errors
|
||||||
func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile.ConfFile) *fuse.Server {
|
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,
|
Cipherdir: args.cipherdir,
|
||||||
PlaintextNames: args.plaintextnames,
|
PlaintextNames: args.plaintextnames,
|
||||||
LongNames: args.longnames,
|
LongNames: args.longnames,
|
||||||
CryptoBackend: cryptoBackend,
|
|
||||||
ConfigCustom: args._configCustom,
|
ConfigCustom: args._configCustom,
|
||||||
Raw64: args.raw64,
|
|
||||||
NoPrealloc: args.noprealloc,
|
NoPrealloc: args.noprealloc,
|
||||||
HKDF: args.hkdf,
|
|
||||||
SerializeReads: args.serialize_reads,
|
SerializeReads: args.serialize_reads,
|
||||||
ForceDecode: args.forcedecode,
|
ForceDecode: args.forcedecode,
|
||||||
ForceOwner: args._forceOwner,
|
ForceOwner: args._forceOwner,
|
||||||
|
@ -216,10 +223,10 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile
|
||||||
if confFile != nil {
|
if confFile != nil {
|
||||||
// Settings from the config file override command line args
|
// Settings from the config file override command line args
|
||||||
frontendArgs.PlaintextNames = confFile.IsFeatureFlagSet(configfile.FlagPlaintextNames)
|
frontendArgs.PlaintextNames = confFile.IsFeatureFlagSet(configfile.FlagPlaintextNames)
|
||||||
frontendArgs.Raw64 = confFile.IsFeatureFlagSet(configfile.FlagRaw64)
|
args.raw64 = confFile.IsFeatureFlagSet(configfile.FlagRaw64)
|
||||||
frontendArgs.HKDF = confFile.IsFeatureFlagSet(configfile.FlagHKDF)
|
args.hkdf = confFile.IsFeatureFlagSet(configfile.FlagHKDF)
|
||||||
if confFile.IsFeatureFlagSet(configfile.FlagAESSIV) {
|
if confFile.IsFeatureFlagSet(configfile.FlagAESSIV) {
|
||||||
frontendArgs.CryptoBackend = cryptocore.BackendAESSIV
|
cryptoBackend = cryptocore.BackendAESSIV
|
||||||
} else if args.reverse {
|
} else if args.reverse {
|
||||||
tlog.Fatal.Printf("AES-SIV is required by reverse mode, but not enabled in the config file")
|
tlog.Fatal.Printf("AES-SIV is required by reverse mode, but not enabled in the config file")
|
||||||
os.Exit(exitcodes.Usage)
|
os.Exit(exitcodes.Usage)
|
||||||
|
@ -232,8 +239,6 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile
|
||||||
}
|
}
|
||||||
jsonBytes, _ := json.MarshalIndent(frontendArgs, "", "\t")
|
jsonBytes, _ := json.MarshalIndent(frontendArgs, "", "\t")
|
||||||
tlog.Debug.Printf("frontendArgs: %s", string(jsonBytes))
|
tlog.Debug.Printf("frontendArgs: %s", string(jsonBytes))
|
||||||
var finalFs pathfs.FileSystem
|
|
||||||
var ctlSockBackend ctlsock.Interface
|
|
||||||
// pathFsOpts are passed into go-fuse/pathfs
|
// pathFsOpts are passed into go-fuse/pathfs
|
||||||
pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}
|
pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}
|
||||||
if args.sharedstorage {
|
if args.sharedstorage {
|
||||||
|
@ -242,21 +247,23 @@ func initFuseFrontend(masterkey []byte, args *argContainer, confFile *configfile
|
||||||
// https://github.com/rfjakob/gocryptfs/issues/156
|
// https://github.com/rfjakob/gocryptfs/issues/156
|
||||||
pathFsOpts.ClientInodes = false
|
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 {
|
if args.reverse {
|
||||||
// The dance with the intermediate variables is because we need to
|
if cryptoBackend != cryptocore.BackendAESSIV {
|
||||||
// cast the FS into pathfs.FileSystem *and* ctlsock.Interface. This
|
log.Panic("reverse mode must use AES-SIV, everything else is insecure")
|
||||||
// avoids using interface{}.
|
}
|
||||||
fs := fusefrontend_reverse.NewFS(masterkey, frontendArgs)
|
fs = fusefrontend_reverse.NewFS(frontendArgs, cEnc, nameTransform)
|
||||||
finalFs = fs
|
|
||||||
ctlSockBackend = fs
|
|
||||||
// Reverse mode is read-only, so we don't need a working link().
|
// Reverse mode is read-only, so we don't need a working link().
|
||||||
// Disable hard link tracking to avoid strange breakage on duplicate
|
// Disable hard link tracking to avoid strange breakage on duplicate
|
||||||
// inode numbers ( https://github.com/rfjakob/gocryptfs/issues/149 ).
|
// inode numbers ( https://github.com/rfjakob/gocryptfs/issues/149 ).
|
||||||
pathFsOpts.ClientInodes = false
|
pathFsOpts.ClientInodes = false
|
||||||
} else {
|
} else {
|
||||||
fs := fusefrontend.NewFS(masterkey, frontendArgs)
|
fs = fusefrontend.NewFS(frontendArgs, cEnc, nameTransform)
|
||||||
finalFs = fs
|
|
||||||
ctlSockBackend = fs
|
|
||||||
}
|
}
|
||||||
// fusefrontend / fusefrontend_reverse have initialized their crypto with
|
// fusefrontend / fusefrontend_reverse have initialized their crypto with
|
||||||
// derived keys (HKDF), we can purge the master key from memory.
|
// 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
|
// We have opened the socket early so that we cannot fail here after
|
||||||
// asking the user for the password
|
// asking the user for the password
|
||||||
if args._ctlsockFd != nil {
|
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
|
var fuseOpts *nodefs.Options
|
||||||
if args.sharedstorage {
|
if args.sharedstorage {
|
||||||
// sharedstorage mode sets all cache timeouts to zero so changes to the
|
// sharedstorage mode sets all cache timeouts to zero so changes to the
|
||||||
|
|
Loading…
Reference in New Issue