diff options
Diffstat (limited to 'internal/nametransform/xattr.go')
-rw-r--r-- | internal/nametransform/xattr.go | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/internal/nametransform/xattr.go b/internal/nametransform/xattr.go new file mode 100644 index 0000000..0aa0fd8 --- /dev/null +++ b/internal/nametransform/xattr.go @@ -0,0 +1,47 @@ +package nametransform + +import ( + "fmt" + "strings" + "syscall" + + "github.com/rfjakob/gocryptfs/v2/internal/tlog" +) + +// xattr names are encrypted like file names, but with a fixed IV. +// Padded with "_xx" for length 16. +var xattrNameIV = []byte("xattr_name_iv_xx") + +func isValidXattrName(name string) error { + if name == "" { + return fmt.Errorf("empty input") + } + if strings.Contains(name, "\000") { + return fmt.Errorf("contains forbidden null byte") + } + return nil +} + +// EncryptXattrName encrypts an extended attribute (xattr) name. +// xattr names are encrypted like file names, but with a fixed IV, and fewer +// naming restriction. +func (n *NameTransform) EncryptXattrName(plainName string) (cipherName64 string, err error) { + if err := isValidXattrName(plainName); err != nil { + tlog.Warn.Printf("EncryptXattrName %q: invalid plainName: %v", plainName, err) + return "", syscall.EBADMSG + } + return n.encryptName(plainName, xattrNameIV), nil +} + +// DecryptName calls decryptName to try and decrypt a base64-encoded encrypted +// filename "cipherName", and failing that checks if it can be bypassed +func (n *NameTransform) DecryptXattrName(cipherName string) (plainName string, err error) { + if plainName, err = n.decryptName(cipherName, xattrNameIV); err != nil { + return "", err + } + if err := isValidXattrName(plainName); err != nil { + tlog.Warn.Printf("DecryptXattrName %q: invalid name after decryption: %v", cipherName, err) + return "", syscall.EBADMSG + } + return plainName, err +} |