Skip to content
This repository was archived by the owner on Jan 17, 2021. It is now read-only.

Commit eee34f5

Browse files
committed
add ~/.ssh directory sanity check before starting
Checks: - if it exists - if it's a directory (if not warn and disable reuse connection feature) - if it has safe permissions (not writable by anyone except the owner, if not then warn)
1 parent 4d64fc0 commit eee34f5

File tree

1 file changed

+43
-3
lines changed

1 file changed

+43
-3
lines changed

sshcode.go

+43-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
)
2222

2323
const codeServerPath = "~/.cache/sshcode/sshcode-server"
24-
const sshControlPath = "~/.ssh/control-%h-%p-%r"
24+
const sshDirectory = "~/.ssh"
25+
const sshDirectoryUnsafeModeMask = 0022
26+
const sshControlPath = sshDirectory + "/control-%h-%p-%r"
2527

2628
type options struct {
2729
skipSync bool
@@ -34,8 +36,6 @@ type options struct {
3436
}
3537

3638
func sshCode(host, dir string, o options) error {
37-
flog.Info("ensuring code-server is updated...")
38-
3939
host, extraSSHFlags, err := parseHost(host)
4040
if err != nil {
4141
return xerrors.Errorf("failed to parse host IP: %w", err)
@@ -56,6 +56,28 @@ func sshCode(host, dir string, o options) error {
5656
return xerrors.Errorf("failed to find available remote port: %w", err)
5757
}
5858

59+
// Check the SSH directory's permissions and warn the user if it is not safe.
60+
sshDirectoryMode, err := os.Lstat(expandPath(sshDirectory))
61+
if err != nil {
62+
if !o.noReuseConnection {
63+
flog.Info("failed to stat %v directory, disabling connection reuse feature: %v", sshDirectory, err)
64+
o.noReuseConnection = true
65+
}
66+
} else {
67+
if !sshDirectoryMode.IsDir() {
68+
if !o.noReuseConnection {
69+
flog.Info("%v is not a directory, disabling connection reuse feature", sshDirectory)
70+
o.noReuseConnection = true
71+
} else {
72+
flog.Info("warning: %v is not a directory", sshDirectory)
73+
}
74+
}
75+
if sshDirectoryMode.Mode().Perm()&sshDirectoryUnsafeModeMask != 0 {
76+
flog.Info("warning: the %v directory has unsafe permissions, they should only be writable by "+
77+
"the owner (and files inside should be set to 0600)", sshDirectory)
78+
}
79+
}
80+
5981
// Start SSH master connection socket. This prevents multiple password prompts from appearing as authentication
6082
// only happens on the initial connection.
6183
if !o.noReuseConnection {
@@ -100,6 +122,7 @@ func sshCode(host, dir string, o options) error {
100122
}
101123
}
102124

125+
flog.Info("ensuring code-server is updated...")
103126
dlScript := downloadScript(codeServerPath)
104127

105128
// Downloads the latest code-server and allows it to be executed.
@@ -214,6 +237,23 @@ func sshCode(host, dir string, o options) error {
214237
return nil
215238
}
216239

240+
// expandPath returns an expanded version of path.
241+
func expandPath(path string) string {
242+
path = filepath.Clean(os.ExpandEnv(path))
243+
244+
// Replace tilde notation in path with the home directory.
245+
homedir := os.Getenv("HOME")
246+
if homedir != "" {
247+
if path == "~" {
248+
path = homedir
249+
} else if strings.HasPrefix(path, "~/") {
250+
path = filepath.Join(homedir, path[2:])
251+
}
252+
}
253+
254+
return filepath.Clean(path)
255+
}
256+
217257
func parseBindAddr(bindAddr string) (string, error) {
218258
if bindAddr == "" {
219259
bindAddr = ":"

0 commit comments

Comments
 (0)