From 650629a936381e55d8bbc629c46f620d575fb634 Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Mon, 23 May 2016 16:11:41 +0200 Subject: [PATCH] [SSH] Allow private keys with 0400 permissions Signed-off-by: Bilal Amarni --- libmachine/ssh/client.go | 9 ++++--- libmachine/ssh/client_test.go | 44 ++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/libmachine/ssh/client.go b/libmachine/ssh/client.go index b356247890..499df4af32 100644 --- a/libmachine/ssh/client.go +++ b/libmachine/ssh/client.go @@ -332,9 +332,12 @@ func NewExternalClient(sshBinaryPath, user, host string, port int, auth *Auth) ( mode := fi.Mode() log.Debugf("Using SSH private key: %s (%s)", privateKeyPath, mode) // Private key file should have strict permissions - if mode != 0600 { - // Abort with correct message - return nil, fmt.Errorf("Permissions %#o for '%s' are too open.", mode, privateKeyPath) + perm := mode.Perm() + if perm&0400 == 0 { + return nil, fmt.Errorf("'%s' is not readable", privateKeyPath) + } + if perm&0077 != 0 { + return nil, fmt.Errorf("permissions %#o for '%s' are too open", perm, privateKeyPath) } } args = append(args, "-i", privateKeyPath) diff --git a/libmachine/ssh/client_test.go b/libmachine/ssh/client_test.go index 2ca3d41d3c..5610c1c0e6 100644 --- a/libmachine/ssh/client_test.go +++ b/libmachine/ssh/client_test.go @@ -1,6 +1,9 @@ package ssh import ( + "fmt" + "io/ioutil" + "os" "runtime" "testing" @@ -46,39 +49,58 @@ func TestGetSSHCmdArgs(t *testing.T) { } func TestNewExternalClient(t *testing.T) { + keyFile, err := ioutil.TempFile("", "docker-machine-tests-dummy-private-key") + if err != nil { + t.Fatal(err) + } + defer keyFile.Close() + + keyFilename := keyFile.Name() + defer os.Remove(keyFilename) + cases := []struct { sshBinaryPath string user string host string port int auth *Auth + perm os.FileMode expectedError string skipOS string }{ { - sshBinaryPath: "/usr/local/bin/ssh", - user: "docker", - host: "localhost", - port: 22, auth: &Auth{Keys: []string{"/tmp/private-key-not-exist"}}, expectedError: "stat /tmp/private-key-not-exist: no such file or directory", skipOS: "none", }, { - sshBinaryPath: "/usr/local/bin/ssh", - user: "docker", - host: "localhost", - port: 22, - auth: &Auth{Keys: []string{"/dev/null"}}, - expectedError: "Permissions 0410000666 for '/dev/null' are too open.", + auth: &Auth{Keys: []string{keyFilename}}, + perm: 0400, + skipOS: "windows", + }, + { + auth: &Auth{Keys: []string{keyFilename}}, + perm: 0100, + expectedError: fmt.Sprintf("'%s' is not readable", keyFilename), + skipOS: "windows", + }, + { + auth: &Auth{Keys: []string{keyFilename}}, + perm: 0644, + expectedError: fmt.Sprintf("permissions 0644 for '%s' are too open", keyFilename), skipOS: "windows", }, } for _, c := range cases { if runtime.GOOS != c.skipOS { + keyFile.Chmod(c.perm) _, err := NewExternalClient(c.sshBinaryPath, c.user, c.host, c.port, c.auth) - assert.EqualError(t, err, c.expectedError) + if c.expectedError != "" { + assert.EqualError(t, err, c.expectedError) + } else { + assert.Equal(t, err, nil) + } } } }