Added auto decryption of invalid file names

Changed invalid file decoding and decryption. Function
DecryptName now shortens the filename until the filename is
decodable and decryptable. Will work with valid **and**
invalid Base64URL delimiter (valid delimiter [0-9a-zA-z_\\-].
If the filename is not decryptable at all, it returns the
original cipher name with flag suffix Changed cli tests to
generate decryptable and undecryptable file names with correct
encrypted content. Replacing #474, extends #393
This commit is contained in:
DerDonut 2020-05-19 13:34:58 +02:00 committed by Jakob Unterwurzacher
parent a56e7cc5ac
commit a8230d271f
2 changed files with 65 additions and 12 deletions

View File

@ -61,7 +61,14 @@ func (n *NameTransform) DecryptName(cipherName string, iv []byte) (string, error
for _, pattern := range n.BadnamePatterns { for _, pattern := range n.BadnamePatterns {
match, err := filepath.Match(pattern, cipherName) match, err := filepath.Match(pattern, cipherName)
if err == nil && match { // Pattern should have been validated already if err == nil && match { // Pattern should have been validated already
return "GOCRYPTFS_BAD_NAME " + cipherName, nil //find longest decryptable substring
for charpos := len(cipherName) - 1; charpos > 0; charpos-- {
res, err = n.decryptName(cipherName[:charpos], iv)
if err == nil {
return res + cipherName[charpos:] + " GOCRYPTFS_BAD_NAME", nil
}
}
return cipherName + " GOCRYPTFS_BAD_NAME", nil
} }
} }
} }

View File

@ -705,40 +705,86 @@ func TestSymlinkedCipherdir(t *testing.T) {
func TestBadname(t *testing.T) { func TestBadname(t *testing.T) {
dir := test_helpers.InitFS(t) dir := test_helpers.InitFS(t)
mnt := dir + ".mnt" mnt := dir + ".mnt"
validFileName := "file"
invalidSuffix := ".invalid_file"
//use static suffix for testing
test_helpers.MountOrFatal(t, dir, mnt, "-badname=*", "-extpass=echo test") test_helpers.MountOrFatal(t, dir, mnt, "-badname=*", "-extpass=echo test")
defer test_helpers.UnmountPanic(mnt) defer test_helpers.UnmountPanic(mnt)
file := mnt + "/file" //write one valid file
file := mnt + "/" + validFileName
err := ioutil.WriteFile(file, []byte("somecontent"), 0600) err := ioutil.WriteFile(file, []byte("somecontent"), 0600)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
invalid_file_name := "invalid_file" //read encrypted file name
invalid_file := dir + "/" + invalid_file_name fread, err := os.Open(dir)
err = ioutil.WriteFile(invalid_file, []byte("somecontent"), 0600) if err != nil {
t.Fatal(err)
}
defer fread.Close()
encryptedfilename := ""
ciphernames, err := fread.Readdirnames(0)
if err != nil {
t.Fatal(err)
}
for _, ciphername := range ciphernames {
if ciphername != "gocryptfs.conf" && ciphername != "gocryptfs.diriv" {
encryptedfilename = ciphername
//found cipher name of "file"
}
}
//Read encrypted file name to generated invalid filenames
fsource, err := os.Open(dir + "/" + encryptedfilename)
if err != nil {
t.Fatal(err)
}
content, err := ioutil.ReadAll(fsource)
if err != nil {
t.Fatal(err)
}
fsource.Close()
//write invalid file which should be decodable
err = ioutil.WriteFile(dir+"/"+encryptedfilename+invalidSuffix, content, 0600)
if err != nil {
t.Fatal(err)
}
//write invalid file which is not decodable (cropping the encrpyted file name)
err = ioutil.WriteFile(dir+"/"+encryptedfilename[:len(encryptedfilename)-2]+invalidSuffix, content, 0600)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
//check for filenames
f, err := os.Open(mnt) f, err := os.Open(mnt)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer f.Close() defer f.Close()
names, err := f.Readdirnames(0) names, err := f.Readdirnames(0)
found := false if err != nil {
t.Fatal(err)
}
foundDecodable := false
foundUndecodable := false
for _, name := range names { for _, name := range names {
if strings.Contains(name, invalid_file_name) { if strings.Contains(name, validFileName+invalidSuffix+" GOCRYPTFS_BAD_NAME") {
found = true foundDecodable = true
break } else if strings.Contains(name, encryptedfilename[:len(encryptedfilename)-2]+invalidSuffix+" GOCRYPTFS_BAD_NAME") {
foundUndecodable = true
} }
} }
if !found { if !foundDecodable {
t.Errorf("did not find invalid name %s in %v", invalid_file_name, names) t.Errorf("did not find invalid name %s in %v", validFileName+invalidSuffix+" GOCRYPTFS_BAD_NAME", names)
}
if !foundUndecodable {
t.Errorf("did not find invalid name %s in %v", encryptedfilename[:len(encryptedfilename)-2]+invalidSuffix+" GOCRYPTFS_BAD_NAME", names)
} }
} }