From 4d466c3412918346144dff609d8f706c6f002581 Mon Sep 17 00:00:00 2001 From: Jakob Unterwurzacher Date: Wed, 25 Nov 2015 19:30:32 +0100 Subject: [PATCH] diriv: Create gocryptfs.diriv in every directory --- cryptfs/cryptfs.go | 2 ++ cryptfs/cryptfs_names.go | 2 +- main.go | 13 +++++++++++++ password.go | 2 +- pathfs_frontend/fs.go | 39 ++++++++++++++++++++++++++++++++------- 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/cryptfs/cryptfs.go b/cryptfs/cryptfs.go index 783bfb8..63febc3 100644 --- a/cryptfs/cryptfs.go +++ b/cryptfs/cryptfs.go @@ -14,6 +14,8 @@ const ( NONCE_LEN = 12 AUTH_TAG_LEN = 16 BLOCK_OVERHEAD = NONCE_LEN + AUTH_TAG_LEN + DIRIV_LEN = 16 // identical to AES block size + DIRIV_FILENAME = "gocryptfs.diriv" ) type CryptFS struct { diff --git a/cryptfs/cryptfs_names.go b/cryptfs/cryptfs_names.go index a7a9a8c..1282f53 100644 --- a/cryptfs/cryptfs_names.go +++ b/cryptfs/cryptfs_names.go @@ -31,7 +31,7 @@ func (be *CryptFS) decryptName(cipherName string) (string, error) { } if len(bin)%aes.BlockSize != 0 { - return "", errors.New(fmt.Sprintf("Name len=%d is not a multiple of 16", len(bin))) + return "", fmt.Errorf("Decoded length %d is not a multiple of the AES block size", len(bin)) } iv := make([]byte, aes.BlockSize) // TODO ? diff --git a/main.go b/main.go index 8d8ef08..77b722a 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "io/ioutil" "flag" "fmt" "os" @@ -43,6 +44,18 @@ func initDir(args *argContainer) { os.Exit(ERREXIT_INIT) } + // 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) + if err != nil { + fmt.Println(err) + os.Exit(ERREXIT_INIT) + } + + // Create gocryptfs.conf cryptfs.Info.Printf("Choose a password for protecting your files.\n") password := readPasswordTwice(args.extpass) err = cryptfs.CreateConfFile(args.config, password, args.plaintextnames) diff --git a/password.go b/password.go index ede65dd..45b0296 100644 --- a/password.go +++ b/password.go @@ -12,7 +12,7 @@ import ( func readPasswordTwice(extpass string) string { fmt.Printf("Password: ") p1 := readPassword(extpass) - fmt.Printf("Repeat: ") + fmt.Printf("Repeat: ") p2 := readPassword(extpass) if p1 != p2 { fmt.Printf("Passwords do not match\n") diff --git a/pathfs_frontend/fs.go b/pathfs_frontend/fs.go index c0a3a41..3d6d79c 100644 --- a/pathfs_frontend/fs.go +++ b/pathfs_frontend/fs.go @@ -1,7 +1,8 @@ package pathfs_frontend import ( - "fmt" + "syscall" + "io/ioutil" "os" "path/filepath" "time" @@ -14,7 +15,7 @@ import ( type FS struct { *cryptfs.CryptFS - pathfs.FileSystem // loopbackFileSystem + pathfs.FileSystem // loopbackFileSystem, see go-fuse/fuse/pathfs/loopback.go backing string // Backing directory } @@ -27,7 +28,8 @@ func NewFS(key []byte, backing string, useOpenssl bool, plaintextNames bool) *FS } } -// GetPath - get the absolute path of the backing file +// GetPath - get the absolute encrypted path of the backing file +// from the relative plaintext path "relPath" func (fs *FS) GetPath(relPath string) string { return filepath.Join(fs.backing, fs.EncryptPath(relPath)) } @@ -63,9 +65,13 @@ 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 + continue + } name, err := fs.DecryptPath(cName) if err != nil { - fmt.Printf("Invalid name \"%s\" in dir \"%s\": %s\n", cName, name, err) + cryptfs.Warn.Printf("Invalid name \"%s\" in dir \"%s\": %s\n", cName, dirName, err) continue } cipherEntries[i].Name = name @@ -160,11 +166,30 @@ func (fs *FS) Readlink(name string, context *fuse.Context) (out string, status f return dstPlain, status } -func (fs *FS) Mkdir(path string, mode uint32, context *fuse.Context) (code fuse.Status) { - if fs.CryptFS.IsFiltered(path) { +func (fs *FS) Mkdir(relPath string, mode uint32, context *fuse.Context) (code fuse.Status) { + if fs.CryptFS.IsFiltered(relPath) { return fuse.EPERM } - return fs.FileSystem.Mkdir(fs.EncryptPath(path), mode, context) + encPath := fs.GetPath(relPath) + diriv := cryptfs.RandBytes(cryptfs.DIRIV_LEN) + dirivPath := filepath.Join(encPath, cryptfs.DIRIV_FILENAME) + // Create directory + err := os.Mkdir(encPath, os.FileMode(mode)) + if err != nil { + return fuse.ToStatus(err) + } + // Create gocryptfs.diriv inside + // 0444 permissions: the file is not secret but should not be written to + err = ioutil.WriteFile(dirivPath, diriv, 0444) + if err != nil { + cryptfs.Warn.Printf("Creating %s in dir %s failed: %v\n", cryptfs.DIRIV_FILENAME, encPath, err) + err2 := syscall.Rmdir(encPath) + if err2 != nil { + cryptfs.Warn.Printf("Removing broken directory failed: %v\n", err2) + } + return fuse.ToStatus(err) + } + return fuse.OK } func (fs *FS) Unlink(name string, context *fuse.Context) (code fuse.Status) {