|
2 | 2 |
|
3 | 3 | package cli
|
4 | 4 |
|
| 5 | +import ( |
| 6 | +"strings" |
| 7 | + |
| 8 | +"golang.org/x/xerrors" |
| 9 | +) |
| 10 | + |
5 | 11 | varhideForceUnixSlashes=true
|
| 12 | + |
| 13 | +// sshConfigMatchExecEscape prepares the path for use in `Match exec` statement. |
| 14 | +// |
| 15 | +// OpenSSH parses the Match line with a very simple tokenizer that accepts "-enclosed strings for the exec command, and |
| 16 | +// has no supported escape sequences for ". This means we cannot include " within the command to execute. |
| 17 | +funcsshConfigMatchExecEscape(pathstring) (string,error) { |
| 18 | +// This is unlikely to ever happen, but newlines are allowed on |
| 19 | +// certain filesystems, but cannot be used inside ssh config. |
| 20 | +ifstrings.ContainsAny(path,"\n") { |
| 21 | +return"",xerrors.Errorf("invalid path: %s",path) |
| 22 | +} |
| 23 | +// Quotes are allowed in path names on unix-like file systems, but OpenSSH's parsing of `Match exec` doesn't allow |
| 24 | +// them. |
| 25 | +ifstrings.Contains(path,`"`) { |
| 26 | +return"",xerrors.Errorf("path must not contain quotes: %q",path) |
| 27 | +} |
| 28 | + |
| 29 | +// OpenSSH passes the match exec string directly to the user's shell. sh, bash and zsh accept spaces and tabs |
| 30 | +// simply escaped by a `\`. It's hard to predict exactly what more exotic shells might do, but this should work for |
| 31 | +// macOS and most Linux distros in their default configuration. |
| 32 | +path=strings.ReplaceAll(path," ","\\ ") |
| 33 | +path=strings.ReplaceAll(path,"\t","\\\t") |
| 34 | +returnpath,nil |
| 35 | +} |