diff options
| -rw-r--r-- | internal/nametransform/names.go | 9 | ||||
| -rw-r--r-- | tests/cli/cli_test.go | 68 | 
2 files changed, 65 insertions, 12 deletions
| diff --git a/internal/nametransform/names.go b/internal/nametransform/names.go index e9f9346..675ed34 100644 --- a/internal/nametransform/names.go +++ b/internal/nametransform/names.go @@ -61,7 +61,14 @@ func (n *NameTransform) DecryptName(cipherName string, iv []byte) (string, error  		for _, pattern := range n.BadnamePatterns {  			match, err := filepath.Match(pattern, cipherName)  			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  			}  		}  	} diff --git a/tests/cli/cli_test.go b/tests/cli/cli_test.go index 2484cf3..08abed9 100644 --- a/tests/cli/cli_test.go +++ b/tests/cli/cli_test.go @@ -705,40 +705,86 @@ func TestSymlinkedCipherdir(t *testing.T) {  func TestBadname(t *testing.T) {  	dir := test_helpers.InitFS(t)  	mnt := dir + ".mnt" +	validFileName := "file" +	invalidSuffix := ".invalid_file" +	//use static suffix for testing  	test_helpers.MountOrFatal(t, dir, mnt, "-badname=*", "-extpass=echo test")  	defer test_helpers.UnmountPanic(mnt) -	file := mnt + "/file" +	//write one valid file +	file := mnt + "/" + validFileName  	err := ioutil.WriteFile(file, []byte("somecontent"), 0600)  	if err != nil {  		t.Fatal(err)  	} -	invalid_file_name := "invalid_file" -	invalid_file := dir + "/" + invalid_file_name -	err = ioutil.WriteFile(invalid_file, []byte("somecontent"), 0600) +	//read encrypted file name +	fread, err := os.Open(dir) +	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 {  		t.Fatal(err)  	} +	//check for filenames  	f, err := os.Open(mnt)  	if err != nil {  		t.Fatal(err)  	}  	defer f.Close() -  	names, err := f.Readdirnames(0) -	found := false +	if err != nil { +		t.Fatal(err) +	} +	foundDecodable := false +	foundUndecodable := false  	for _, name := range names { -		if strings.Contains(name, invalid_file_name) { -			found = true -			break +		if strings.Contains(name, validFileName+invalidSuffix+" GOCRYPTFS_BAD_NAME") { +			foundDecodable = true +		} else if strings.Contains(name, encryptedfilename[:len(encryptedfilename)-2]+invalidSuffix+" GOCRYPTFS_BAD_NAME") { +			foundUndecodable = true  		}  	} -	if !found { -		t.Errorf("did not find invalid name %s in %v", invalid_file_name, names) +	if !foundDecodable { +		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)  	}  } | 
