reverse: factor out rDecryptName

This prepares the code for the introduction of a path cache.
This commit is contained in:
Jakob Unterwurzacher 2017-01-03 17:46:11 +01:00
parent 2643dd0ea5
commit ef089c9f80
1 changed files with 40 additions and 32 deletions

View File

@ -44,46 +44,54 @@ func (rfs *ReverseFS) abs(relPath string, err error) (string, error) {
return filepath.Join(rfs.args.Cipherdir, relPath), nil
}
func (rfs *ReverseFS) rDecryptName(cName string, dirIV []byte, pDir string) (pName string, err error) {
nameType := nametransform.NameType(cName)
if nameType == nametransform.LongNameNone {
pName, err = rfs.nameTransform.DecryptName(cName, dirIV)
if err != nil {
// We get lots of decrypt requests for names like ".Trash" that
// are invalid base64. Convert them to ENOENT so the correct
// error gets returned to the user.
if _, ok := err.(base64.CorruptInputError); ok {
return "", syscall.ENOENT
}
// Stat attempts on the link target of encrypted symlinks.
// These are always valid base64 but the length is not a
// multiple of 16.
if err == syscall.EINVAL {
return "", syscall.ENOENT
}
return "", err
}
} else if nameType == nametransform.LongNameContent {
pName, err = rfs.findLongnameParent(pDir, dirIV, cName)
if err != nil {
return "", err
}
} else {
// It makes no sense to decrypt a ".name" file. This is a virtual file
// that has no represantation in the plaintext filesystem. ".name"
// files should have already been handled in virtualfile.go.
tlog.Warn.Printf("decryptPath: tried to decrypt %q!? Returning EINVAL.", cName)
return "", syscall.EINVAL
}
return pName, nil
}
func (rfs *ReverseFS) decryptPath(relPath string) (string, error) {
if rfs.args.PlaintextNames || relPath == "" {
return relPath, nil
}
var err error
var transformedParts []string
parts := strings.Split(relPath, "/")
for i, part := range parts {
var transformedParts []string
for i := range parts {
// Start at the top and recurse
currentCipherDir := filepath.Join(parts[:i]...)
nameType := nametransform.NameType(part)
currentPlainDir := filepath.Join(transformedParts[:i]...)
dirIV := derivePathIV(currentCipherDir, ivPurposeDirIV)
var transformedPart string
if nameType == nametransform.LongNameNone {
transformedPart, err = rfs.nameTransform.DecryptName(part, dirIV)
if err != nil {
// We get lots of decrypt requests for names like ".Trash" that
// are invalid base64. Convert them to ENOENT so the correct
// error gets returned to the user.
if _, ok := err.(base64.CorruptInputError); ok {
return "", syscall.ENOENT
}
// Stat attempts on the link target of encrypted symlinks.
// These are always valid base64 but the length is not a
// multiple of 16.
if err == syscall.EINVAL {
return "", syscall.ENOENT
}
return "", err
}
} else if nameType == nametransform.LongNameContent {
currentPlainDir := filepath.Join(transformedParts[:i]...)
transformedPart, err = rfs.findLongnameParent(currentPlainDir, dirIV, part)
if err != nil {
return "", err
}
} else {
// It makes no sense to decrypt a ".name" file
tlog.Warn.Printf("decryptPath: tried to decrypt %q!? Returning EINVAL.", part)
return "", syscall.EINVAL
transformedPart, err := rfs.rDecryptName(parts[i], dirIV, currentPlainDir)
if err != nil {
return "", err
}
transformedParts = append(transformedParts, transformedPart)
}