diff options
Diffstat (limited to 'internal/fusefrontend_reverse')
| -rw-r--r-- | internal/fusefrontend_reverse/node_helpers.go | 16 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/node_xattr.go | 2 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/node_xattr_freebsd.go | 17 | ||||
| -rw-r--r-- | internal/fusefrontend_reverse/root_node.go | 32 |
4 files changed, 53 insertions, 14 deletions
diff --git a/internal/fusefrontend_reverse/node_helpers.go b/internal/fusefrontend_reverse/node_helpers.go index 3165db6..dc8d928 100644 --- a/internal/fusefrontend_reverse/node_helpers.go +++ b/internal/fusefrontend_reverse/node_helpers.go @@ -17,13 +17,13 @@ import ( ) const ( - // File names are padded to 16-byte multiples, encrypted and - // base64-encoded. We can encode at most 176 bytes to stay below the 255 - // bytes limit: - // * base64(176 bytes) = 235 bytes - // * base64(192 bytes) = 256 bytes (over 255!) - // But the PKCS#7 padding is at least one byte. This means we can only use - // 175 bytes for the file name. +// File names are padded to 16-byte multiples, encrypted and +// base64-encoded. We can encode at most 176 bytes to stay below the 255 +// bytes limit: +// * base64(176 bytes) = 235 bytes +// * base64(192 bytes) = 256 bytes (over 255!) +// But the PKCS#7 padding is at least one byte. This means we can only use +// 175 bytes for the file name. ) // translateSize translates the ciphertext size in `out` into plaintext size. @@ -134,7 +134,7 @@ func (n *Node) lookupLongnameName(ctx context.Context, nameFile string, out *fus if errno != 0 { return } - if rn.isExcludedPlain(filepath.Join(d.cPath, pName)) { + if rn.isExcludedPlain(filepath.Join(d.pPath, pName)) { errno = syscall.EPERM return } diff --git a/internal/fusefrontend_reverse/node_xattr.go b/internal/fusefrontend_reverse/node_xattr.go index f22764a..b940339 100644 --- a/internal/fusefrontend_reverse/node_xattr.go +++ b/internal/fusefrontend_reverse/node_xattr.go @@ -40,7 +40,7 @@ func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, } else { pAttr, err := rn.decryptXattrName(attr) if err != nil { - return 0, syscall.EINVAL + return 0, noSuchAttributeError } pData, errno := n.getXAttr(pAttr) if errno != 0 { diff --git a/internal/fusefrontend_reverse/node_xattr_freebsd.go b/internal/fusefrontend_reverse/node_xattr_freebsd.go new file mode 100644 index 0000000..949cf15 --- /dev/null +++ b/internal/fusefrontend_reverse/node_xattr_freebsd.go @@ -0,0 +1,17 @@ +package fusefrontend_reverse + +import ( + "golang.org/x/sys/unix" +) + +const noSuchAttributeError = unix.ENOATTR + +func (n *Node) getXAttr(cAttr string) (out []byte, errno unix.Errno) { + // TODO + return nil, unix.EOPNOTSUPP +} + +func (n *Node) listXAttr() (out []string, errno unix.Errno) { + // TODO + return nil, unix.EOPNOTSUPP +} diff --git a/internal/fusefrontend_reverse/root_node.go b/internal/fusefrontend_reverse/root_node.go index 420ed22..461b25c 100644 --- a/internal/fusefrontend_reverse/root_node.go +++ b/internal/fusefrontend_reverse/root_node.go @@ -13,6 +13,7 @@ import ( "github.com/hanwen/go-fuse/v2/fs" "github.com/hanwen/go-fuse/v2/fuse" + "github.com/rfjakob/gocryptfs/v2/internal/configfile" "github.com/rfjakob/gocryptfs/v2/internal/contentenc" "github.com/rfjakob/gocryptfs/v2/internal/exitcodes" "github.com/rfjakob/gocryptfs/v2/internal/fusefrontend" @@ -35,6 +36,11 @@ type RootNode struct { contentEnc *contentenc.ContentEnc // Tests whether a path is excluded (hidden) from the user. Used by -exclude. excluder ignore.IgnoreParser + // configPlainPath is the path of a custom config file (-config), relative to + // Cipherdir, set only when that file is located inside Cipherdir. Such a file + // is hidden from the encrypted view, otherwise it would leak in encrypted + // form (https://github.com/rfjakob/gocryptfs/issues/1009). + configPlainPath string // inoMap translates inode numbers from different devices to unique inode // numbers. inoMap *inomap.InoMap @@ -62,7 +68,7 @@ func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransf var rootDev uint64 var st syscall.Stat_t var statErr error - var shortNameMax int + var shortNameMax = syscall.NAME_MAX if statErr = syscall.Stat(args.Cipherdir, &st); statErr != nil { tlog.Warn.Printf("Could not stat backing directory %q: %v", args.Cipherdir, statErr) if args.OneFileSystem { @@ -73,8 +79,10 @@ func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransf rootDev = uint64(st.Dev) } - shortNameMax = n.GetLongNameMax() * 3 / 4 - shortNameMax = shortNameMax - shortNameMax%16 - 1 + if !args.PlaintextNames { + shortNameMax = n.GetLongNameMax() * 3 / 4 + shortNameMax = shortNameMax - shortNameMax%16 - 1 + } rn := &RootNode{ args: args, @@ -91,6 +99,14 @@ func NewRootNode(args fusefrontend.Args, c *contentenc.ContentEnc, n *nametransf if len(args.Exclude) > 0 || len(args.ExcludeWildcard) > 0 || len(args.ExcludeFrom) > 0 { rn.excluder = prepareExcluder(args) } + // A custom config file (-config) located inside Cipherdir must be hidden from + // the encrypted view, otherwise it leaks there in encrypted form (#1009). + if args.ConfigCustom && args.Config != "" { + if rel, err := filepath.Rel(args.Cipherdir, args.Config); err == nil && + rel != "." && rel != ".." && !strings.HasPrefix(rel, ".."+string(filepath.Separator)) { + rn.configPlainPath = rel + } + } return rn } @@ -136,9 +152,15 @@ func (rn *RootNode) findLongnameParent(fd int, diriv []byte, longname string) (p // excluded (used when -exclude is passed by the user). func (rn *RootNode) isExcludedPlain(pPath string) bool { // root dir can't be excluded - if pPath == "" { + // Don't exclude gocryptfs.conf too + if pPath == "" || pPath == configfile.ConfReverseName { return false } + // A custom config file (-config) inside Cipherdir is hidden from the + // encrypted view (https://github.com/rfjakob/gocryptfs/issues/1009). + if rn.configPlainPath != "" && pPath == rn.configPlainPath { + return true + } return rn.excluder != nil && rn.excluder.MatchesPath(pPath) } @@ -146,7 +168,7 @@ func (rn *RootNode) isExcludedPlain(pPath string) bool { // pDir is the relative plaintext path to the directory these entries are // from. The entries should be plaintext files. func (rn *RootNode) excludeDirEntries(d *dirfdPlus, entries []fuse.DirEntry) (filtered []fuse.DirEntry) { - if rn.excluder == nil { + if rn.excluder == nil && rn.configPlainPath == "" { return entries } filtered = make([]fuse.DirEntry, 0, len(entries)) |
