diff options
| -rw-r--r-- | cryptfs/config_file.go | 3 | ||||
| -rw-r--r-- | cryptfs/names_diriv.go | 5 | ||||
| -rw-r--r-- | integration_tests/example_filesystems_test.go | 2 | ||||
| -rw-r--r-- | integration_tests/helpers.go | 5 | ||||
| -rw-r--r-- | main.go | 34 | ||||
| -rw-r--r-- | pathfs_frontend/fs.go | 11 | ||||
| -rw-r--r-- | pathfs_frontend/names.go | 12 | 
7 files changed, 44 insertions, 28 deletions
diff --git a/cryptfs/config_file.go b/cryptfs/config_file.go index 1e7e3b3..a0ab218 100644 --- a/cryptfs/config_file.go +++ b/cryptfs/config_file.go @@ -47,8 +47,11 @@ func CreateConfFile(filename string, password string, plaintextNames bool) error  	// This sets ScryptObject and EncryptedKey  	cf.EncryptKey(key, password) +	// Set defaults  	cf.Version = HEADER_CURRENT_VERSION +	cf.FeatureFlags = []string{FlagDirIV} +	// Set values chosen by the user  	if plaintextNames {  		cf.FeatureFlags = append(cf.FeatureFlags, FlagPlaintextNames)  	} diff --git a/cryptfs/names_diriv.go b/cryptfs/names_diriv.go index ab039f0..6346bc2 100644 --- a/cryptfs/names_diriv.go +++ b/cryptfs/names_diriv.go @@ -22,8 +22,9 @@ func (be *CryptFS) readDirIV(dir string) (iv []byte, err error) {  }  // WriteDirIV - create diriv file inside "dir" (absolute path) -// This function is exported because it is used from pathfs_frontend -func (be *CryptFS) WriteDirIV(dir string) error { +// This function is exported because it is used from pathfs_frontend, main, +// and also the automated tests. +func WriteDirIV(dir string) error {  	iv := RandBytes(DIRIV_LEN)  	file := filepath.Join(dir, DIRIV_FILENAME)  	// 0444 permissions: the file is not secret but should not be written to diff --git a/integration_tests/example_filesystems_test.go b/integration_tests/example_filesystems_test.go index 644f8e7..7924736 100644 --- a/integration_tests/example_filesystems_test.go +++ b/integration_tests/example_filesystems_test.go @@ -36,7 +36,7 @@ func TestExampleFsNormal(t *testing.T) {  	checkStatusTxt(t, pDir+"status.txt")  	unmount(pDir)  	mount(cDir, pDir, "-masterkey", "74676e34-0b47c145-00dac61a-17a92316-"+ -		"bb57044c-e205b71f-65f4fdca-7cabd4b3") +		"bb57044c-e205b71f-65f4fdca-7cabd4b3", "-diriv=false")  	checkStatusTxt(t, pDir+"status.txt")  	unmount(pDir)  	err = os.Remove(pDir) diff --git a/integration_tests/helpers.go b/integration_tests/helpers.go index 6fc65cf..bff4e5b 100644 --- a/integration_tests/helpers.go +++ b/integration_tests/helpers.go @@ -8,6 +8,8 @@ import (  	"os"  	"os/exec"  	"testing" + +	"github.com/rfjakob/gocryptfs/cryptfs"  )  // Note: the code assumes that all have a trailing slash @@ -38,8 +40,7 @@ func resetTmpDir() {  		fmt.Println(err)  		os.Exit(1)  	} -	dirIV := make([]byte, 16) -	err = ioutil.WriteFile(defaultCipherDir+"gocryptfs.diriv", dirIV, 0444) +	err = cryptfs.WriteDirIV(defaultCipherDir)  	if err != nil {  		fmt.Println(err)  		os.Exit(1) @@ -3,7 +3,6 @@ package main  import (  	"flag"  	"fmt" -	"io/ioutil"  	"os"  	"os/exec"  	"os/signal" @@ -34,6 +33,15 @@ const (  	ERREXIT_MOUNTPOINT = 10  ) +type argContainer struct { +	debug, init, zerokey, fusedebug, openssl, passwd, foreground, version, +	plaintextnames, quiet, diriv bool +	masterkey, mountpoint, cipherdir, cpuprofile, config, extpass string +	notifypid                                                     int +} + +var flagSet *flag.FlagSet +  // GitVersion will be set by the build script "build.bash"  var GitVersion = "[version not set - please compile using ./build.bash]" @@ -45,11 +53,7 @@ func initDir(args *argContainer) {  	}  	// Create gocryptfs.diriv in the root dir -	diriv := cryptfs.RandBytes(cryptfs.DIRIV_LEN) -	dirivPath := filepath.Join(args.cipherdir, cryptfs.DIRIV_FILENAME) -	cryptfs.Debug.Printf("Creating %s\n", dirivPath) -	// 0444 permissions: the file is not secret but should not be written to -	err = ioutil.WriteFile(dirivPath, diriv, 0444) +	err = cryptfs.WriteDirIV(args.cipherdir)  	if err != nil {  		fmt.Println(err)  		os.Exit(ERREXIT_INIT) @@ -76,15 +80,6 @@ func usageText() {  	flagSet.PrintDefaults()  } -type argContainer struct { -	debug, init, zerokey, fusedebug, openssl, passwd, foreground, version, -	plaintextnames, quiet bool -	masterkey, mountpoint, cipherdir, cpuprofile, config, extpass string -	notifypid                                                     int -} - -var flagSet *flag.FlagSet -  // loadConfig - load the config file "filename", prompting the user for the password  func loadConfig(args *argContainer) (masterkey []byte, confFile *cryptfs.ConfFile) {  	// Check if the file exists at all before prompting for a password @@ -133,9 +128,9 @@ func printVersion() {  func main() {  	runtime.GOMAXPROCS(4)  	var err error +	var args argContainer  	// Parse command line arguments -	var args argContainer  	flagSet = flag.NewFlagSet(PROGRAM_NAME, flag.ExitOnError)  	flagSet.Usage = usageText  	flagSet.BoolVar(&args.debug, "debug", false, "Enable debug output") @@ -149,6 +144,7 @@ func main() {  	flagSet.BoolVar(&args.plaintextnames, "plaintextnames", false, "Do not encrypt "+  		"file names")  	flagSet.BoolVar(&args.quiet, "q", false, "Quiet - silence informational messages") +	flagSet.BoolVar(&args.diriv, "diriv", true, "Use per-directory file name IV")  	flagSet.StringVar(&args.masterkey, "masterkey", "", "Mount with explicit master key")  	flagSet.StringVar(&args.cpuprofile, "cpuprofile", "", "Write cpu profile to specified file")  	flagSet.StringVar(&args.config, "config", "", "Use specified config file instead of CIPHERDIR/gocryptfs.conf") @@ -264,7 +260,9 @@ func main() {  		var confFile *cryptfs.ConfFile  		masterkey, confFile = loadConfig(&args)  		printMasterKey(masterkey) +		// Settings from the config file override command line args  		args.plaintextnames = confFile.IsFeatureFlagSet(cryptfs.FlagPlaintextNames) +		args.diriv = confFile.IsFeatureFlagSet(cryptfs.FlagDirIV)  	}  	// Initialize FUSE server  	srv := pathfsFrontend(masterkey, args) @@ -285,7 +283,7 @@ func main() {  // Calls os.Exit on errors  func pathfsFrontend(key []byte, args argContainer) *fuse.Server { -	finalFs := pathfs_frontend.NewFS(key, args.cipherdir, args.openssl, args.plaintextnames) +	finalFs := pathfs_frontend.NewFS(key, args.cipherdir, args.openssl, args.plaintextnames, args.diriv)  	pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}  	pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts)  	fuseOpts := &nodefs.Options{ @@ -309,7 +307,7 @@ func pathfsFrontend(key []byte, args argContainer) *fuse.Server {  		fmt.Printf("Mount failed: %v", err)  		os.Exit(ERREXIT_MOUNT)  	} -	srv.SetDebug(args.debug) +	srv.SetDebug(args.fusedebug)  	return srv  } diff --git a/pathfs_frontend/fs.go b/pathfs_frontend/fs.go index 680b08c..c2b80a3 100644 --- a/pathfs_frontend/fs.go +++ b/pathfs_frontend/fs.go @@ -19,6 +19,8 @@ type FS struct {  	*cryptfs.CryptFS  	pathfs.FileSystem        // loopbackFileSystem, see go-fuse/fuse/pathfs/loopback.go  	backingDir        string // Backing directory, cipherdir +	// Are per-directory filename IVs enabled? +	dirIV bool  	// dirIVLock: Lock()ed if any "gocryptfs.diriv" file is modified  	// Readers must RLock() it to prevent them from seeing intermediate  	// states @@ -26,10 +28,11 @@ type FS struct {  }  // Encrypted FUSE overlay filesystem -func NewFS(key []byte, backing string, useOpenssl bool, plaintextNames bool) *FS { +func NewFS(key []byte, backing string, useOpenssl bool, plaintextNames bool, dirIV bool) *FS {  	return &FS{  		CryptFS:    cryptfs.NewCryptFS(key, useOpenssl, plaintextNames),  		FileSystem: pathfs.NewLoopbackFileSystem(backing), +		dirIV:      dirIV,  		backingDir: backing,  	}  } @@ -82,8 +85,8 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f  				// silently ignore "gocryptfs.conf" in the top level dir  				continue  			} -			if cName == cryptfs.DIRIV_FILENAME { -				// silently ignore "gocryptfs.diriv" everywhere +			if fs.dirIV && cName == cryptfs.DIRIV_FILENAME { +				// silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled  				continue  			}  			name, err := fs.decryptPath(cName) @@ -227,7 +230,7 @@ func (fs *FS) Mkdir(relPath string, mode uint32, context *fuse.Context) (code fu  		return fuse.ToStatus(err)  	}  	// Create gocryptfs.diriv inside -	err = fs.CryptFS.WriteDirIV(encPath) +	err = cryptfs.WriteDirIV(encPath)  	if err != nil {  		// This should not happen  		cryptfs.Warn.Printf("Creating %s in dir %s failed: %v\n", cryptfs.DIRIV_FILENAME, encPath, err) diff --git a/pathfs_frontend/names.go b/pathfs_frontend/names.go index 9c6e010..122b3dd 100644 --- a/pathfs_frontend/names.go +++ b/pathfs_frontend/names.go @@ -1,14 +1,24 @@  package pathfs_frontend -// This file handles filename encryption +// This file forwards file encryption operations to cryptfs + +import ( +	"github.com/rfjakob/gocryptfs/cryptfs" +)  func (fs *FS) encryptPath(plainPath string) (string, error) { +	if !fs.dirIV { +		return fs.CryptFS.TranslatePathZeroIV(plainPath, cryptfs.OpEncrypt) +	}  	fs.dirIVLock.RLock()  	defer fs.dirIVLock.RUnlock()  	return fs.CryptFS.EncryptPathDirIV(plainPath, fs.backingDir)  }  func (fs *FS) decryptPath(cipherPath string) (string, error) { +	if !fs.dirIV { +		return fs.CryptFS.TranslatePathZeroIV(cipherPath, cryptfs.OpDecrypt) +	}  	fs.dirIVLock.RLock()  	defer fs.dirIVLock.RUnlock()  	return fs.CryptFS.DecryptPathDirIV(cipherPath, fs.backingDir)  | 
