diff options
| author | Jakob Unterwurzacher | 2015-11-28 16:52:57 +0100 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2015-11-28 18:39:45 +0100 | 
| commit | 1fb349e97b5972b5d56c61afd05aed26698dcc97 (patch) | |
| tree | 935bfa1d2dc57569680ed32e3d79b34f326e7b6b | |
| parent | 01141f8b5e0e51ea07299b7bf43d27feb53f6c67 (diff) | |
diriv: also support old CBC symlink
| -rw-r--r-- | main.go | 30 | ||||
| -rw-r--r-- | pathfs_frontend/args.go | 10 | ||||
| -rw-r--r-- | pathfs_frontend/fs.go | 48 | ||||
| -rw-r--r-- | pathfs_frontend/names.go | 8 | 
4 files changed, 70 insertions, 26 deletions
| @@ -245,6 +245,7 @@ func main() {  	}  	// Get master key  	var masterkey []byte +	var confFile *cryptfs.ConfFile  	if args.masterkey != "" {  		// "-masterkey"  		cryptfs.Info.Printf("Using explicit master key.\n") @@ -257,15 +258,12 @@ func main() {  		masterkey = make([]byte, cryptfs.KEY_LEN)  	} else {  		// Load master key from config file -		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) +	cryptfs.Debug.Printf("args: %v\n", args) +	srv := pathfsFrontend(masterkey, args, confFile)  	cryptfs.Info.Println("Filesystem ready.")  	// We are ready - send USR1 signal to our parent  	if args.notifypid > 0 { @@ -279,11 +277,27 @@ func main() {  	// main exits with code 0  } -// pathfsFrontend - initialize FUSE server based on go-fuse's PathFS. +// pathfsFrontend - initialize gocryptfs/pathfs_frontend  // Calls os.Exit on errors -func pathfsFrontend(key []byte, args argContainer) *fuse.Server { +func pathfsFrontend(key []byte, args argContainer, confFile *cryptfs.ConfFile) *fuse.Server { + +	// Reconciliate CLI and config file arguments into a Args struct that is passed to the +	// filesystem implementation +	frontendArgs := pathfs_frontend.Args{ +		Cipherdir: args.cipherdir, +		Masterkey: key, +		OpenSSL: args.openssl, +		PlaintextNames: args.plaintextnames, +		DirIV: args.diriv, +	} +	// confFile is nil when "-zerokey" or "-masterkey" was used +	if confFile != nil { +		// Settings from the config file override command line args +		frontendArgs.PlaintextNames = confFile.IsFeatureFlagSet(cryptfs.FlagPlaintextNames) +		frontendArgs.DirIV = confFile.IsFeatureFlagSet(cryptfs.FlagDirIV) +	} -	finalFs := pathfs_frontend.NewFS(key, args.cipherdir, args.openssl, args.plaintextnames, args.diriv) +	finalFs := pathfs_frontend.NewFS(frontendArgs)  	pathFsOpts := &pathfs.PathNodeFsOptions{ClientInodes: true}  	pathFs := pathfs.NewPathNodeFs(finalFs, pathFsOpts)  	fuseOpts := &nodefs.Options{ diff --git a/pathfs_frontend/args.go b/pathfs_frontend/args.go new file mode 100644 index 0000000..7971b79 --- /dev/null +++ b/pathfs_frontend/args.go @@ -0,0 +1,10 @@ +package pathfs_frontend + +// Container for arguments that are passed from main() to pathfs_frontend +type Args struct { +	Masterkey []byte +	Cipherdir string +	OpenSSL bool +	PlaintextNames bool +	DirIV bool +} diff --git a/pathfs_frontend/fs.go b/pathfs_frontend/fs.go index dbb6b10..e68e6bc 100644 --- a/pathfs_frontend/fs.go +++ b/pathfs_frontend/fs.go @@ -18,9 +18,7 @@ import (  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 +	args Args                // Stores configuration arguments  	// dirIVLock: Lock()ed if any "gocryptfs.diriv" file is modified  	// Readers must RLock() it to prevent them from seeing intermediate  	// states @@ -28,23 +26,24 @@ type FS struct {  }  // Encrypted FUSE overlay filesystem -func NewFS(key []byte, backing string, useOpenssl bool, plaintextNames bool, dirIV bool) *FS { +func NewFS(args Args) *FS {  	return &FS{ -		CryptFS:    cryptfs.NewCryptFS(key, useOpenssl, plaintextNames), -		FileSystem: pathfs.NewLoopbackFileSystem(backing), -		dirIV:      dirIV, -		backingDir: backing, +		CryptFS:    cryptfs.NewCryptFS(args.Masterkey, args.OpenSSL, args.PlaintextNames), +		FileSystem: pathfs.NewLoopbackFileSystem(args.Cipherdir), +		args: args,  	}  }  // GetBackingPath - get the absolute encrypted path of the backing file  // from the relative plaintext path "relPath"  func (fs *FS) getBackingPath(relPath string) (string, error) { -	encrypted, err := fs.encryptPath(relPath) +	cPath, err := fs.encryptPath(relPath)  	if err != nil {  		return "", err  	} -	return filepath.Join(fs.backingDir, encrypted), nil +	cAbsPath := filepath.Join(fs.args.Cipherdir, cPath) +	cryptfs.Debug.Printf("getBackingPath: %s + %s -> %s\n", fs.args.Cipherdir, relPath, cAbsPath) +	return cAbsPath, nil  }  func (fs *FS) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) { @@ -85,12 +84,12 @@ func (fs *FS) OpenDir(dirName string, context *fuse.Context) ([]fuse.DirEntry, f  				// silently ignore "gocryptfs.conf" in the top level dir  				continue  			} -			if fs.dirIV && cName == cryptfs.DIRIV_FILENAME { +			if fs.args.DirIV && cName == cryptfs.DIRIV_FILENAME {  				// silently ignore "gocryptfs.diriv" everywhere if dirIV is enabled  				continue  			}  			var name string -			if !fs.dirIV { +			if !fs.args.DirIV {  				name, err = fs.decryptPath(cName)  			} else {  				// When dirIV is enabled we need the full path to be able to decrypt it @@ -123,15 +122,16 @@ func (fs *FS) mangleOpenFlags(flags uint32) (newFlags int, writeOnly bool) {  }  func (fs *FS) Open(path string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) { -	cryptfs.Debug.Printf("Open(%s)\n", path)  	if fs.CryptFS.IsFiltered(path) {  		return nil, fuse.EPERM  	}  	iflags, writeOnly := fs.mangleOpenFlags(flags)  	cPath, err := fs.getBackingPath(path)  	if err != nil { +		cryptfs.Debug.Printf("Open: getBackingPath: %v\n", err)  		return nil, fuse.ToStatus(err)  	} +	cryptfs.Debug.Printf("Open: %s\n", cPath)  	f, err := os.OpenFile(cPath, iflags, 0666)  	if err != nil {  		return nil, fuse.ToStatus(err) @@ -214,6 +214,16 @@ func (fs *FS) Readlink(path string, context *fuse.Context) (out string, status f  	if status != fuse.OK {  		return "", status  	} +	// Old filesystem: symlinks are encrypted like paths (CBC) +	if !fs.args.DirIV { +		target, err := fs.decryptPath(cTarget) +		if err != nil { +			cryptfs.Warn.Printf("Readlink: CBC decryption failed: %v", err) +			return "", fuse.EIO +		} +		return target, fuse.OK +	} +	// Since gocryptfs v0.5 symlinks are encrypted like file contents (GCM)  	cBinTarget, err := base64.URLEncoding.DecodeString(cTarget)  	if err != nil {  		cryptfs.Warn.Printf("Readlink: %v\n", err) @@ -335,7 +345,17 @@ func (fs *FS) Symlink(target string, linkName string, context *fuse.Context) (co  	if err != nil {  		return fuse.ToStatus(err)  	} - +	// Old filesystem: symlinks are encrypted like paths (CBC) +	if !fs.args.DirIV { +		cTarget, err := fs.encryptPath(target) +		if err != nil { +			cryptfs.Warn.Printf("Symlink: BUG: we should not get an error here: %v\n", err) +			return fuse.ToStatus(err) +		} +		err = os.Symlink(cTarget, cPath) +		return fuse.ToStatus(err) +	} +	// Since gocryptfs v0.5 symlinks are encrypted like file contents (GCM)  	cBinTarget := fs.CryptFS.EncryptBlock([]byte(target), 0, nil)  	cTarget := base64.URLEncoding.EncodeToString(cBinTarget) diff --git a/pathfs_frontend/names.go b/pathfs_frontend/names.go index 122b3dd..bb73ff4 100644 --- a/pathfs_frontend/names.go +++ b/pathfs_frontend/names.go @@ -7,19 +7,19 @@ import (  )  func (fs *FS) encryptPath(plainPath string) (string, error) { -	if !fs.dirIV { +	if !fs.args.DirIV {  		return fs.CryptFS.TranslatePathZeroIV(plainPath, cryptfs.OpEncrypt)  	}  	fs.dirIVLock.RLock()  	defer fs.dirIVLock.RUnlock() -	return fs.CryptFS.EncryptPathDirIV(plainPath, fs.backingDir) +	return fs.CryptFS.EncryptPathDirIV(plainPath, fs.args.Cipherdir)  }  func (fs *FS) decryptPath(cipherPath string) (string, error) { -	if !fs.dirIV { +	if !fs.args.DirIV {  		return fs.CryptFS.TranslatePathZeroIV(cipherPath, cryptfs.OpDecrypt)  	}  	fs.dirIVLock.RLock()  	defer fs.dirIVLock.RUnlock() -	return fs.CryptFS.DecryptPathDirIV(cipherPath, fs.backingDir) +	return fs.CryptFS.DecryptPathDirIV(cipherPath, fs.args.Cipherdir)  } | 
