diff options
author | Jakob Unterwurzacher | 2016-11-10 23:32:51 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2016-11-10 23:32:51 +0100 |
commit | c03fc46a5150715bf6aee20ce4b89d9704141220 (patch) | |
tree | aa7cb2a5cf9a068f4867702d4846e04cf6da3e02 | |
parent | d3764b775395faa31afb1db34c5c2814a0e9af09 (diff) |
ctlsock: implement EncryptPath for reverse mode, add tests
13 files changed, 139 insertions, 33 deletions
diff --git a/internal/fusefrontend/ctlsock_interface.go b/internal/fusefrontend/ctlsock_interface.go index c22dce6..619d747 100644 --- a/internal/fusefrontend/ctlsock_interface.go +++ b/internal/fusefrontend/ctlsock_interface.go @@ -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?)") } diff --git a/internal/fusefrontend_reverse/ctlsock_interface.go b/internal/fusefrontend_reverse/ctlsock_interface.go index 376814d..1f02fc1 100644 --- a/internal/fusefrontend_reverse/ctlsock_interface.go +++ b/internal/fusefrontend_reverse/ctlsock_interface.go @@ -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 } diff --git a/tests/defaults/main_test.go b/tests/defaults/main_test.go index 8733c8b..95835a4 100644 --- a/tests/defaults/main_test.go +++ b/tests/defaults/main_test.go @@ -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) - } - defer conn.Close() - conn.SetDeadline(time.Now().Add(time.Second)) - msg := []byte(`{"EncryptPath": "foobar"}`) - _, err = conn.Write(msg) - if err != nil { - t.Fatal(err) + req := ctlsock.RequestStruct{ + EncryptPath: "foobar", } - 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) } } diff --git a/tests/reverse/ctlsock_reverse_test_fs/.gocryptfs.reverse.conf b/tests/reverse/ctlsock_reverse_test_fs/.gocryptfs.reverse.conf new file mode 100644 index 0000000..9bd9259 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/.gocryptfs.reverse.conf @@ -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" + ] +} diff --git a/tests/reverse/ctlsock_reverse_test_fs/dir/dir/file b/tests/reverse/ctlsock_reverse_test_fs/dir/dir/file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/dir/dir/file diff --git a/tests/reverse/ctlsock_reverse_test_fs/dir/file b/tests/reverse/ctlsock_reverse_test_fs/dir/file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/dir/file diff --git a/tests/reverse/ctlsock_reverse_test_fs/dir/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx b/tests/reverse/ctlsock_reverse_test_fs/dir/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/dir/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/tests/reverse/ctlsock_reverse_test_fs/file b/tests/reverse/ctlsock_reverse_test_fs/file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/file diff --git a/tests/reverse/ctlsock_reverse_test_fs/longdir.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file b/tests/reverse/ctlsock_reverse_test_fs/longdir.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/longdir.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/file diff --git a/tests/reverse/ctlsock_reverse_test_fs/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx b/tests/reverse/ctlsock_reverse_test_fs/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/reverse/ctlsock_reverse_test_fs/longfile.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx diff --git a/tests/reverse/ctlsock_test.go b/tests/reverse/ctlsock_test.go new file mode 100644 index 0000000..0e4a29b --- /dev/null +++ b/tests/reverse/ctlsock_test.go @@ -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) + } + } +} diff --git a/tests/reverse/main_test.go b/tests/reverse/main_test.go index a2b7eb6..be6016f 100644 --- a/tests/reverse/main_test.go +++ b/tests/reverse/main_test.go @@ -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"} diff --git a/tests/test_helpers/helpers.go b/tests/test_helpers/helpers.go index aec1f7c..1bbfdf3 100644 --- a/tests/test_helpers/helpers.go +++ b/tests/test_helpers/helpers.go @@ -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 +} |