diff options
| author | Jakob Unterwurzacher | 2016-08-25 00:14:36 +0200 | 
|---|---|---|
| committer | Jakob Unterwurzacher | 2016-09-25 16:43:17 +0200 | 
| commit | 9237b4f53e13075b595131f68edcfb2c831d684e (patch) | |
| tree | cba9163085dfb18ca8db4c62ca71c24bd6ff804b | |
| parent | f6d4d240e6e17f8052cdecd11533a1e24b339985 (diff) | |
reverse: add skeleton
Compiles but does not do much else.
| -rw-r--r-- | internal/fusefrontend_reverse/rfile.go | 27 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/rfs.go | 93 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/rpath.go | 56 | 
3 files changed, 176 insertions, 0 deletions
| diff --git a/internal/fusefrontend_reverse/rfile.go b/internal/fusefrontend_reverse/rfile.go new file mode 100644 index 0000000..746a0d6 --- /dev/null +++ b/internal/fusefrontend_reverse/rfile.go @@ -0,0 +1,27 @@ +package fusefrontend_reverse + +import ( +	"os" + +	"github.com/hanwen/go-fuse/fuse" +	"github.com/hanwen/go-fuse/fuse/nodefs" + +	"github.com/rfjakob/gocryptfs/internal/contentenc" +) + +type file struct { +	fd *os.File +	// Content encryption helper +	contentEnc *contentenc.ContentEnc + +	// nodefs.defaultFile returns ENOSYS for all operations +	nodefs.File +} + +func NewFile(fd *os.File, contentEnc *contentenc.ContentEnc) (nodefs.File, fuse.Status) { +	return &file{ +		fd:         fd, +		contentEnc: contentEnc, +		File:       nodefs.NewDefaultFile(), +	}, fuse.OK +} diff --git a/internal/fusefrontend_reverse/rfs.go b/internal/fusefrontend_reverse/rfs.go new file mode 100644 index 0000000..914dccb --- /dev/null +++ b/internal/fusefrontend_reverse/rfs.go @@ -0,0 +1,93 @@ +package fusefrontend_reverse + +import ( +	"os" + +	"github.com/hanwen/go-fuse/fuse" +	"github.com/hanwen/go-fuse/fuse/nodefs" +	"github.com/hanwen/go-fuse/fuse/pathfs" + +	"github.com/rfjakob/gocryptfs/internal/contentenc" +	"github.com/rfjakob/gocryptfs/internal/cryptocore" +	"github.com/rfjakob/gocryptfs/internal/fusefrontend" +	"github.com/rfjakob/gocryptfs/internal/nametransform" +) + +type FS struct { +	// loopbackFileSystem, see go-fuse/fuse/pathfs/loopback.go +	pathfs.FileSystem +	// Stores configuration arguments +	args fusefrontend.Args +	// Filename encryption helper +	nameTransform *nametransform.NameTransform +	// Content encryption helper +	contentEnc *contentenc.ContentEnc +} + +// Encrypted FUSE overlay filesystem +func NewFS(args fusefrontend.Args) *FS { +	cryptoCore := cryptocore.New(args.Masterkey, args.OpenSSL, true) +	contentEnc := contentenc.New(cryptoCore, contentenc.DefaultBS) +	nameTransform := nametransform.New(cryptoCore, args.LongNames) + +	return &FS{ +		FileSystem:    pathfs.NewLoopbackFileSystem(args.Cipherdir), +		args:          args, +		nameTransform: nameTransform, +		contentEnc:    contentEnc, +	} +} + +func (fs *FS) GetAttr(relPath string, context *fuse.Context) (*fuse.Attr, fuse.Status) { +	if fs.isFiltered(relPath) { +		return nil, fuse.EPERM +	} +	relPath, err := fs.decryptPath(relPath) +	if err != nil { +		return nil, fuse.ToStatus(err) +	} +	a, status := fs.FileSystem.GetAttr(relPath, context) +	if a == nil { +		return a, status +	} +	// Calculate encrypted file size +	if a.IsRegular() { +		a.Size = fs.contentEnc.PlainSizeToCipherSize(a.Size) +	} +	return a, fuse.OK +} + +func (fs *FS) Open(relPath string, flags uint32, context *fuse.Context) (fuseFile nodefs.File, status fuse.Status) { +	if fs.isFiltered(relPath) { +		return nil, fuse.EPERM +	} +	absPath, err := fs.abs(fs.decryptPath(relPath)) +	if err != nil { +		return nil, fuse.ToStatus(err) +	} +	f, err := os.OpenFile(absPath, int(flags), 0666) +	if err != nil { +		return nil, fuse.ToStatus(err) +	} +	return NewFile(f, fs.contentEnc) +} + +func (fs *FS) OpenDir(relPath string, context *fuse.Context) ([]fuse.DirEntry, fuse.Status) { +	relPath, err := fs.decryptPath(relPath) +	if err != nil { +		return nil, fuse.ToStatus(err) +	} +	// Read plaintext dir +	entries, status := fs.FileSystem.OpenDir(relPath, context) +	if entries == nil { +		return nil, status +	} +	// Encrypt names +	for i := range entries { +		entries[i].Name, err = fs.encryptPath(entries[i].Name) +		if err != nil { +			return nil, fuse.ToStatus(err) +		} +	} +	return entries, fuse.OK +} diff --git a/internal/fusefrontend_reverse/rpath.go b/internal/fusefrontend_reverse/rpath.go new file mode 100644 index 0000000..9377958 --- /dev/null +++ b/internal/fusefrontend_reverse/rpath.go @@ -0,0 +1,56 @@ +package fusefrontend_reverse + +import ( +	"path/filepath" +	"strings" +) + +func (fs *FS) abs(relPath string, err error) (string, error) { +	if err != nil { +		return "", err +	} +	return filepath.Join(fs.args.Cipherdir, relPath), nil +} + +const ( +	ENCRYPT = iota +	DECRYPT +) + +func (fs *FS) encryptPath(relPath string) (string, error) { +	return fs.transformPath(relPath, ENCRYPT) +} + +func (fs *FS) decryptPath(relPath string) (string, error) { +	return fs.transformPath(relPath, DECRYPT) +} + +func (fs *FS) transformPath(relPath string, direction int) (string, error) { +	if fs.args.PlaintextNames { +		return relPath, nil +	} +	var err error +	var transformedParts []string +	iv := make([]byte, 16) +	parts := strings.Split(relPath, "/") +	for _, part := range parts { +		var transformedPart string +		switch direction { +		case ENCRYPT: +			transformedPart = fs.nameTransform.EncryptName(part, iv) +		case DECRYPT: +			transformedPart, err = fs.nameTransform.DecryptName(part, iv) +			if err != nil { +				return "", err +			} +		default: +			panic("bug: invalid direction value") +		} +		transformedParts = append(transformedParts, transformedPart) +	} +	return filepath.Join(transformedParts...), nil +} + +func (fs *FS) isFiltered(relPath string) bool { +	return false +} | 
