|
| 1 | +// Package fusefrontend_reverse interfaces directly with the go-fuse library. |
| 2 | +package fusefrontend_reverse |
| 3 | + |
| 4 | +import ( |
| 5 | + "bytes" |
| 6 | + "context" |
| 7 | + "syscall" |
| 8 | + |
| 9 | + "github.com/rfjakob/gocryptfs/v2/internal/pathiv" |
| 10 | +) |
| 11 | + |
| 12 | +// We store encrypted xattrs under this prefix plus the base64-encoded |
| 13 | +// encrypted original name. |
| 14 | +var xattrStorePrefix = "user.gocryptfs." |
| 15 | + |
| 16 | +// isAcl returns true if the attribute name is for storing ACLs |
| 17 | +// |
| 18 | +// ACLs are passed through without encryption |
| 19 | +func isAcl(attr string) bool { |
| 20 | + return attr == "system.posix_acl_access" || attr == "system.posix_acl_default" |
| 21 | +} |
| 22 | + |
| 23 | +// GetXAttr - FUSE call. Reads the value of extended attribute "attr". |
| 24 | +// |
| 25 | +// This function is symlink-safe through Fgetxattr. |
| 26 | +func (n *Node) Getxattr(ctx context.Context, attr string, dest []byte) (uint32, syscall.Errno) { |
| 27 | + rn := n.rootNode() |
| 28 | + var data []byte |
| 29 | + // ACLs are passed through without encryption |
| 30 | + if isAcl(attr) { |
| 31 | + var errno syscall.Errno |
| 32 | + data, errno = n.getXAttr(attr) |
| 33 | + if errno != 0 { |
| 34 | + return 0, errno |
| 35 | + } |
| 36 | + } else { |
| 37 | + pAttr, err := rn.decryptXattrName(attr) |
| 38 | + if err != nil { |
| 39 | + return 0, syscall.EINVAL |
| 40 | + } |
| 41 | + pData, errno := n.getXAttr(pAttr) |
| 42 | + if errno != 0 { |
| 43 | + return 0, errno |
| 44 | + } |
| 45 | + nonce := pathiv.Derive(n.Path()+"\000"+attr, pathiv.PurposeXattrIV) |
| 46 | + data = rn.encryptXattrValue(pData, nonce) |
| 47 | + } |
| 48 | + if len(dest) < len(data) { |
| 49 | + return uint32(len(data)), syscall.ERANGE |
| 50 | + } |
| 51 | + l := copy(dest, data) |
| 52 | + return uint32(l), 0 |
| 53 | +} |
| 54 | + |
| 55 | +// ListXAttr - FUSE call. Lists extended attributes on the file at "relPath". |
| 56 | +// |
| 57 | +// This function is symlink-safe through Flistxattr. |
| 58 | +func (n *Node) Listxattr(ctx context.Context, dest []byte) (uint32, syscall.Errno) { |
| 59 | + pNames, errno := n.listXAttr() |
| 60 | + if errno != 0 { |
| 61 | + return 0, errno |
| 62 | + } |
| 63 | + rn := n.rootNode() |
| 64 | + var buf bytes.Buffer |
| 65 | + for _, pName := range pNames { |
| 66 | + // ACLs are passed through without encryption |
| 67 | + if isAcl(pName) { |
| 68 | + buf.WriteString(pName + "\000") |
| 69 | + continue |
| 70 | + } |
| 71 | + cName, err := rn.encryptXattrName(pName) |
| 72 | + if err != nil { |
| 73 | + continue |
| 74 | + } |
| 75 | + buf.WriteString(cName + "\000") |
| 76 | + } |
| 77 | + if buf.Len() > len(dest) { |
| 78 | + return uint32(buf.Len()), syscall.ERANGE |
| 79 | + } |
| 80 | + return uint32(copy(dest, buf.Bytes())), 0 |
| 81 | +} |
0 commit comments