2021-12-19 14:43:56 +01:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2021-12-19 14:50:52 +01:00
|
|
|
// DecryptXattrName calls decryptName to try and decrypt a base64-encoded encrypted
|
2021-12-19 14:43:56 +01:00
|
|
|
// 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
|
|
|
|
}
|