ctlsock: implement EncryptPath for reverse mode, add tests
This commit is contained in:
parent
d3764b7753
commit
c03fc46a51
@ -14,6 +14,6 @@ func (fs *FS) EncryptPath(plainPath string) (string, error) {
|
||||
}
|
||||
|
||||
// DecryptPath implements ctlsock.Backend
|
||||
func (fs *FS) DecryptPath(plainPath string) (string, error) {
|
||||
return "", errors.New("Not implemented")
|
||||
func (fs *FS) DecryptPath(cipherPath string) (string, error) {
|
||||
return "", errors.New("not implemented (yet?)")
|
||||
}
|
||||
|
@ -1,19 +1,39 @@
|
||||
package fusefrontend_reverse
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/ctlsock"
|
||||
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
||||
)
|
||||
|
||||
var _ ctlsock.Interface = &ReverseFS{} // Verify that interface is implemented.
|
||||
|
||||
// EncryptPath implements ctlsock.Backend
|
||||
// EncryptPath implements ctlsock.Backend.
|
||||
// This is actually not used inside reverse mode, but we implement it because
|
||||
// third-party tools want to encrypt paths through the control socket.
|
||||
func (rfs *ReverseFS) EncryptPath(plainPath string) (string, error) {
|
||||
return "", errors.New("Not implemented")
|
||||
if rfs.args.PlaintextNames || plainPath == "" {
|
||||
return plainPath, nil
|
||||
}
|
||||
cipherPath := ""
|
||||
parts := strings.Split(plainPath, "/")
|
||||
for _, part := range parts {
|
||||
dirIV := derivePathIV(cipherPath, ivPurposeDirIV)
|
||||
encryptedPart := rfs.nameTransform.EncryptName(part, dirIV)
|
||||
if rfs.args.LongNames && len(encryptedPart) > syscall.NAME_MAX {
|
||||
encryptedPart = nametransform.HashLongName(encryptedPart)
|
||||
}
|
||||
cipherPath = filepath.Join(cipherPath, encryptedPart)
|
||||
}
|
||||
return cipherPath, nil
|
||||
}
|
||||
|
||||
// DecryptPath implements ctlsock.Backend
|
||||
func (rfs *ReverseFS) DecryptPath(plainPath string) (string, error) {
|
||||
return rfs.decryptPath(plainPath)
|
||||
func (rfs *ReverseFS) DecryptPath(cipherPath string) (string, error) {
|
||||
p, err := rfs.decryptPath(cipherPath)
|
||||
//fmt.Printf("rfs DecryptPath: %q -> %q %v\n", cipherPath, p, err)
|
||||
return p, err
|
||||
}
|
||||
|
@ -2,14 +2,10 @@
|
||||
package defaults
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/ctlsock"
|
||||
"github.com/rfjakob/gocryptfs/tests/test_helpers"
|
||||
@ -48,27 +44,16 @@ func TestCtlSock(t *testing.T) {
|
||||
sock := cDir + ".sock"
|
||||
test_helpers.MountOrFatal(t, cDir, pDir, "-ctlsock="+sock, "-extpass", "echo test")
|
||||
defer test_helpers.UnmountPanic(pDir)
|
||||
conn, err := net.DialTimeout("unix", sock, 1*time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
req := ctlsock.RequestStruct{
|
||||
EncryptPath: "foobar",
|
||||
}
|
||||
defer conn.Close()
|
||||
conn.SetDeadline(time.Now().Add(time.Second))
|
||||
msg := []byte(`{"EncryptPath": "foobar"}`)
|
||||
_, err = conn.Write(msg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := make([]byte, 2*syscall.PathMax)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf = buf[:n]
|
||||
var response ctlsock.ResponseStruct
|
||||
json.Unmarshal(buf, &response)
|
||||
response := test_helpers.QueryCtlSock(t, sock, req)
|
||||
if response.Result == "" || response.ErrNo != 0 {
|
||||
fmt.Printf("%s\n", string(buf))
|
||||
t.Errorf("got an error reply")
|
||||
t.Errorf("got an error reply: %+v", response)
|
||||
}
|
||||
req.EncryptPath = "not-existing-dir/xyz"
|
||||
response = test_helpers.QueryCtlSock(t, sock, req)
|
||||
if response.ErrNo != int32(syscall.ENOENT) || response.Result != "" {
|
||||
t.Errorf("incorrect error handling: %+v", response)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
{
|
||||
"Creator": "gocryptfs v1.1.1-16-g75ebb28-dirty",
|
||||
"EncryptedKey": "cE5bhCZl1iL1tn0dNLh8aQy8n55NMbojmmkwM8iM8/y0uChO0CGaK16sNHffAKJ++qH287JlCpk/BFyi",
|
||||
"ScryptObject": {
|
||||
"Salt": "yUxEmtl4KeUkCxL8b6aYcEGVtFe2NAlwy0WsFLt8p+Y=",
|
||||
"N": 1024,
|
||||
"R": 8,
|
||||
"P": 1,
|
||||
"KeyLen": 32
|
||||
},
|
||||
"Version": 2,
|
||||
"FeatureFlags": [
|
||||
"GCMIV128",
|
||||
"DirIV",
|
||||
"EMENames",
|
||||
"LongNames",
|
||||
"AESSIV"
|
||||
]
|
||||
}
|
0
tests/reverse/ctlsock_reverse_test_fs/dir/dir/file
Normal file
0
tests/reverse/ctlsock_reverse_test_fs/dir/dir/file
Normal file
0
tests/reverse/ctlsock_reverse_test_fs/dir/file
Normal file
0
tests/reverse/ctlsock_reverse_test_fs/dir/file
Normal file
0
tests/reverse/ctlsock_reverse_test_fs/file
Normal file
0
tests/reverse/ctlsock_reverse_test_fs/file
Normal file
52
tests/reverse/ctlsock_test.go
Normal file
52
tests/reverse/ctlsock_test.go
Normal file
@ -0,0 +1,52 @@
|
||||
package reverse_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/ctlsock"
|
||||
"github.com/rfjakob/gocryptfs/tests/test_helpers"
|
||||
)
|
||||
|
||||
var ctlSockTestCases = [][]string{
|
||||
{"4RQq1dJlfvQPaVU5Xypf0w==", "file"},
|
||||
{"gocryptfs.longname.ZQCAoi5li3xvDZRO8McBV0L_kzJc4IcAOEzuW-2S1Y4=", "longfile." + x240},
|
||||
{"v6puXntoQOk7Mhl8zJ4Idg==", "dir"},
|
||||
{"v6puXntoQOk7Mhl8zJ4Idg==/UVy2gV0RQTUC8AE4wYoMwg==", "dir/file"},
|
||||
{"v6puXntoQOk7Mhl8zJ4Idg==/fvHFLHlxHCQ7EpVMJu0AZg==", "dir/dir"},
|
||||
{"v6puXntoQOk7Mhl8zJ4Idg==/fvHFLHlxHCQ7EpVMJu0AZg==/_4uudIGniACke55JoDsqDA==", "dir/dir/dir"},
|
||||
{"v6puXntoQOk7Mhl8zJ4Idg==/fvHFLHlxHCQ7EpVMJu0AZg==/QvPahkkeVRKTw2kdZFZxwQ==", "dir/dir/file"},
|
||||
{"v6puXntoQOk7Mhl8zJ4Idg==/gocryptfs.longname.y6rxCn6Id8hIZL2t_STpdLZpu-aE2HpprJR25xD60mk=", "dir/longfile." + x240},
|
||||
{"gocryptfs.longname.cvRximo1ATRJVEzw_V9MZieHFlod9y2iv2Sug1kbiTE=", "longdir." + x240},
|
||||
{"gocryptfs.longname.cvRximo1ATRJVEzw_V9MZieHFlod9y2iv2Sug1kbiTE=/-LMdFgFt6UxO-z5iJvuC9w==", "longdir." + x240 + "/dir"},
|
||||
{"gocryptfs.longname.cvRximo1ATRJVEzw_V9MZieHFlod9y2iv2Sug1kbiTE=/rBPJYAzcHWLdPj1T8kgh8A==", "longdir." + x240 + "/file"},
|
||||
}
|
||||
|
||||
func TestCtlSockDecryptPath(t *testing.T) {
|
||||
mnt, err := ioutil.TempDir(test_helpers.TmpDir, "reverse_mnt_")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sock := mnt + ".sock"
|
||||
test_helpers.MountOrFatal(t, "ctlsock_reverse_test_fs", mnt, "-reverse", "-extpass", "echo test", "-ctlsock="+sock)
|
||||
defer test_helpers.UnmountPanic(mnt)
|
||||
var req ctlsock.RequestStruct
|
||||
for i, tc := range ctlSockTestCases {
|
||||
// Decrypt
|
||||
req = ctlsock.RequestStruct{DecryptPath: tc[0]}
|
||||
response := test_helpers.QueryCtlSock(t, sock, req)
|
||||
if response.ErrNo != 0 {
|
||||
t.Errorf("Testcase %d Decrypt: %q ErrNo=%d ErrText=%s", i, tc[0], response.ErrNo, response.ErrText)
|
||||
} else if response.Result != tc[1] {
|
||||
t.Errorf("Testcase %d Decrypt: Want %q got %q", i, tc[1], response.Result)
|
||||
}
|
||||
// Encrypt
|
||||
req = ctlsock.RequestStruct{EncryptPath: tc[1]}
|
||||
response = test_helpers.QueryCtlSock(t, sock, req)
|
||||
if response.ErrNo != 0 {
|
||||
t.Errorf("Testcase %d Encrypt: %q ErrNo=%d ErrText=%s", i, tc[0], response.ErrNo, response.ErrText)
|
||||
} else if response.Result != tc[0] {
|
||||
t.Errorf("Testcase %d Encrypt: Want %q got %q", i, tc[1], response.Result)
|
||||
}
|
||||
}
|
||||
}
|
@ -9,11 +9,10 @@ import (
|
||||
)
|
||||
|
||||
var dirA, dirB, dirC string
|
||||
var x240 string
|
||||
var x240 = string(bytes.Repeat([]byte("x"), 240))
|
||||
var plaintextnames bool
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
x240 = string(bytes.Repeat([]byte("x"), 240))
|
||||
var r int
|
||||
for _, plaintextnames = range []bool{false, true} {
|
||||
argsA := []string{"-reverse"}
|
||||
|
@ -3,15 +3,19 @@ package test_helpers
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rfjakob/gocryptfs/internal/ctlsock"
|
||||
"github.com/rfjakob/gocryptfs/internal/nametransform"
|
||||
)
|
||||
|
||||
@ -323,3 +327,30 @@ func Du(t *testing.T, fd int) (nBytes int64) {
|
||||
// st.Blocks = number of 512-byte blocks
|
||||
return st.Blocks * 512
|
||||
}
|
||||
|
||||
// QueryCtlSock sends a request to the control socket at "socketPath" and
|
||||
// returns the response.
|
||||
func QueryCtlSock(t *testing.T, socketPath string, req ctlsock.RequestStruct) (response ctlsock.ResponseStruct) {
|
||||
conn, err := net.DialTimeout("unix", socketPath, 1*time.Second)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
conn.SetDeadline(time.Now().Add(time.Second))
|
||||
msg, err := json.Marshal(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = conn.Write(msg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf := make([]byte, 2*syscall.PathMax)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf = buf[:n]
|
||||
json.Unmarshal(buf, &response)
|
||||
return response
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user