aboutsummaryrefslogtreecommitdiff
path: root/internal/fusefrontend_reverse/node_xattr.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/fusefrontend_reverse/node_xattr.go')
-rw-r--r--internal/fusefrontend_reverse/node_xattr.go81
1 files changed, 81 insertions, 0 deletions
diff --git a/internal/fusefrontend_reverse/node_xattr.go b/internal/fusefrontend_reverse/node_xattr.go
new file mode 100644
index 0000000..f4e3bda
--- /dev/null
+++ b/internal/fusefrontend_reverse/node_xattr.go
@@ -0,0 +1,81 @@
+// Package fusefrontend_reverse interfaces directly with the go-fuse library.
+package fusefrontend_reverse
+
+import (
+ "bytes"
+ "context"
+ "syscall"
+
+ "github.com/rfjakob/gocryptfs/v2/internal/pathiv"
+)
+
+// We store encrypted xattrs under this prefix plus the base64-encoded
+// encrypted original name.
+var xattrStorePrefix = "user.gocryptfs."
+
+// isAcl returns true if the attribute name is for storing ACLs
+//
+// ACLs are passed through without encryption
+func isAcl(attr string) bool {
+ return attr == "system.posix_acl_access" || attr == "system.posix_acl_default"
+}
+
+// GetXAttr - FUSE call. Reads the value of extended attribute "attr".
+//
+// This function is symlink-safe through Fgetxattr.
+func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) {
+ rn := n.rootNode()
+ var data []byte
+ // ACLs are passed through without encryption
+ if isAcl(attr) {
+ var errno syscall.Errno
+ data, errno = n.getXAttr(attr)
+ if errno != 0 {
+ return 0, errno
+ }
+ } else {
+ pAttr, err := rn.decryptXattrName(attr)
+ if err != nil {
+ return 0, syscall.EINVAL
+ }
+ pData, errno := n.getXAttr(pAttr)
+ if errno != 0 {
+ return 0, errno
+ }
+ nonce := pathiv.Derive(n.Path()+"\000"+attr, pathiv.PurposeXattrIV)
+ data = rn.encryptXattrValue(pData, nonce)
+ }
+ if len(dest) < len(data) {
+ return uint32(len(data)), syscall.ERANGE
+ }
+ l := copy(dest, data)
+ return uint32(l), 0
+}
+
+// ListXAttr - FUSE call. Lists extended attributes on the file at "relPath".
+//
+// This function is symlink-safe through Flistxattr.
+func (n *Node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) {
+ pNames, errno := n.listXAttr()
+ if errno != 0 {
+ return 0, errno
+ }
+ rn := n.rootNode()
+ var buf bytes.Buffer
+ for _, pName := range pNames {
+ // ACLs are passed through without encryption
+ if isAcl(pName) {
+ buf.WriteString(pName + "\000")
+ continue
+ }
+ cName, err := rn.encryptXattrName(pName)
+ if err != nil {
+ continue
+ }
+ buf.WriteString(cName + "\000")
+ }
+ if buf.Len() > len(dest) {
+ return uint32(buf.Len()), syscall.ERANGE
+ }
+ return uint32(copy(dest, buf.Bytes())), 0
+}