1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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
}
|