aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2015-11-28 16:52:57 +0100
committerJakob Unterwurzacher2015-11-28 18:39:45 +0100
commit1fb349e97b5972b5d56c61afd05aed26698dcc97 (patch)
tree935bfa1d2dc57569680ed32e3d79b34f326e7b6b
parent01141f8b5e0e51ea07299b7bf43d27feb53f6c67 (diff)
diriv: also support old CBC symlink
-rw-r--r--main.go30
-rw-r--r--pathfs_frontend/args.go10
-rw-r--r--pathfs_frontend/fs.go48
-rw-r--r--pathfs_frontend/names.go8
4 files changed, 70 insertions, 26 deletions
diff --git a/main.go b/main.go
index b3944cc..ab2c1f1 100644
--- a/main.go
+++ b/main.go
@@ -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)
}