diff options
| -rw-r--r-- | internal/fusefrontend_reverse/rpath.go | 72 | 
1 files changed, 40 insertions, 32 deletions
| diff --git a/internal/fusefrontend_reverse/rpath.go b/internal/fusefrontend_reverse/rpath.go index edffc1e..af49776 100644 --- a/internal/fusefrontend_reverse/rpath.go +++ b/internal/fusefrontend_reverse/rpath.go @@ -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)  	} | 
