main
Raw Download raw file
  1package ssh_config
  2
  3import (
  4	"fmt"
  5	"strconv"
  6	"strings"
  7)
  8
  9// Default returns the default value for the given keyword, for example "22" if
 10// the keyword is "Port". Default returns the empty string if the keyword has no
 11// default, or if the keyword is unknown. Keyword matching is case-insensitive.
 12//
 13// Default values are provided by OpenSSH_7.4p1 on a Mac.
 14func Default(keyword string) string {
 15	return defaults[strings.ToLower(keyword)]
 16}
 17
 18// Arguments where the value must be "yes" or "no" and *only* yes or no.
 19var yesnos = map[string]bool{
 20	strings.ToLower("BatchMode"):                        true,
 21	strings.ToLower("CanonicalizeFallbackLocal"):        true,
 22	strings.ToLower("ChallengeResponseAuthentication"):  true,
 23	strings.ToLower("CheckHostIP"):                      true,
 24	strings.ToLower("ClearAllForwardings"):              true,
 25	strings.ToLower("Compression"):                      true,
 26	strings.ToLower("EnableSSHKeysign"):                 true,
 27	strings.ToLower("ExitOnForwardFailure"):             true,
 28	strings.ToLower("ForwardAgent"):                     true,
 29	strings.ToLower("ForwardX11"):                       true,
 30	strings.ToLower("ForwardX11Trusted"):                true,
 31	strings.ToLower("GatewayPorts"):                     true,
 32	strings.ToLower("GSSAPIAuthentication"):             true,
 33	strings.ToLower("GSSAPIDelegateCredentials"):        true,
 34	strings.ToLower("HostbasedAuthentication"):          true,
 35	strings.ToLower("IdentitiesOnly"):                   true,
 36	strings.ToLower("KbdInteractiveAuthentication"):     true,
 37	strings.ToLower("NoHostAuthenticationForLocalhost"): true,
 38	strings.ToLower("PasswordAuthentication"):           true,
 39	strings.ToLower("PermitLocalCommand"):               true,
 40	strings.ToLower("PubkeyAuthentication"):             true,
 41	strings.ToLower("RhostsRSAAuthentication"):          true,
 42	strings.ToLower("RSAAuthentication"):                true,
 43	strings.ToLower("StreamLocalBindUnlink"):            true,
 44	strings.ToLower("TCPKeepAlive"):                     true,
 45	strings.ToLower("UseKeychain"):                      true,
 46	strings.ToLower("UsePrivilegedPort"):                true,
 47	strings.ToLower("VisualHostKey"):                    true,
 48}
 49
 50var uints = map[string]bool{
 51	strings.ToLower("CanonicalizeMaxDots"):     true,
 52	strings.ToLower("CompressionLevel"):        true, // 1 to 9
 53	strings.ToLower("ConnectionAttempts"):      true,
 54	strings.ToLower("ConnectTimeout"):          true,
 55	strings.ToLower("NumberOfPasswordPrompts"): true,
 56	strings.ToLower("Port"):                    true,
 57	strings.ToLower("ServerAliveCountMax"):     true,
 58	strings.ToLower("ServerAliveInterval"):     true,
 59}
 60
 61func mustBeYesOrNo(lkey string) bool {
 62	return yesnos[lkey]
 63}
 64
 65func mustBeUint(lkey string) bool {
 66	return uints[lkey]
 67}
 68
 69func validate(key, val string) error {
 70	lkey := strings.ToLower(key)
 71	if mustBeYesOrNo(lkey) && (val != "yes" && val != "no") {
 72		return fmt.Errorf("ssh_config: value for key %q must be 'yes' or 'no', got %q", key, val)
 73	}
 74	if mustBeUint(lkey) {
 75		_, err := strconv.ParseUint(val, 10, 64)
 76		if err != nil {
 77			return fmt.Errorf("ssh_config: %v", err)
 78		}
 79	}
 80	return nil
 81}
 82
 83var defaults = map[string]string{
 84	strings.ToLower("AddKeysToAgent"):                  "no",
 85	strings.ToLower("AddressFamily"):                   "any",
 86	strings.ToLower("BatchMode"):                       "no",
 87	strings.ToLower("CanonicalizeFallbackLocal"):       "yes",
 88	strings.ToLower("CanonicalizeHostname"):            "no",
 89	strings.ToLower("CanonicalizeMaxDots"):             "1",
 90	strings.ToLower("ChallengeResponseAuthentication"): "yes",
 91	strings.ToLower("CheckHostIP"):                     "yes",
 92	// TODO is this still the correct cipher
 93	strings.ToLower("Cipher"):                    "3des",
 94	strings.ToLower("Ciphers"):                   "chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com,aes128-cbc,aes192-cbc,aes256-cbc",
 95	strings.ToLower("ClearAllForwardings"):       "no",
 96	strings.ToLower("Compression"):               "no",
 97	strings.ToLower("CompressionLevel"):          "6",
 98	strings.ToLower("ConnectionAttempts"):        "1",
 99	strings.ToLower("ControlMaster"):             "no",
100	strings.ToLower("EnableSSHKeysign"):          "no",
101	strings.ToLower("EscapeChar"):                "~",
102	strings.ToLower("ExitOnForwardFailure"):      "no",
103	strings.ToLower("FingerprintHash"):           "sha256",
104	strings.ToLower("ForwardAgent"):              "no",
105	strings.ToLower("ForwardX11"):                "no",
106	strings.ToLower("ForwardX11Timeout"):         "20m",
107	strings.ToLower("ForwardX11Trusted"):         "no",
108	strings.ToLower("GatewayPorts"):              "no",
109	strings.ToLower("GlobalKnownHostsFile"):      "/etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2",
110	strings.ToLower("GSSAPIAuthentication"):      "no",
111	strings.ToLower("GSSAPIDelegateCredentials"): "no",
112	strings.ToLower("HashKnownHosts"):            "no",
113	strings.ToLower("HostbasedAuthentication"):   "no",
114
115	strings.ToLower("HostbasedKeyTypes"): "ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,ssh-rsa",
116	strings.ToLower("HostKeyAlgorithms"): "ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,ssh-rsa",
117	// HostName has a dynamic default (the value passed at the command line).
118
119	strings.ToLower("IdentitiesOnly"): "no",
120	strings.ToLower("IdentityFile"):   "~/.ssh/identity",
121
122	// IPQoS has a dynamic default based on interactive or non-interactive
123	// sessions.
124
125	strings.ToLower("KbdInteractiveAuthentication"): "yes",
126
127	strings.ToLower("KexAlgorithms"): "curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1",
128	strings.ToLower("LogLevel"):      "INFO",
129	strings.ToLower("MACs"):          "umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1",
130
131	strings.ToLower("NoHostAuthenticationForLocalhost"): "no",
132	strings.ToLower("NumberOfPasswordPrompts"):          "3",
133	strings.ToLower("PasswordAuthentication"):           "yes",
134	strings.ToLower("PermitLocalCommand"):               "no",
135	strings.ToLower("Port"):                             "22",
136
137	strings.ToLower("PreferredAuthentications"): "gssapi-with-mic,hostbased,publickey,keyboard-interactive,password",
138	strings.ToLower("Protocol"):                 "2",
139	strings.ToLower("ProxyUseFdpass"):           "no",
140	strings.ToLower("PubkeyAcceptedKeyTypes"):   "ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,ssh-rsa",
141	strings.ToLower("PubkeyAuthentication"):     "yes",
142	strings.ToLower("RekeyLimit"):               "default none",
143	strings.ToLower("RhostsRSAAuthentication"):  "no",
144	strings.ToLower("RSAAuthentication"):        "yes",
145
146	strings.ToLower("ServerAliveCountMax"):   "3",
147	strings.ToLower("ServerAliveInterval"):   "0",
148	strings.ToLower("StreamLocalBindMask"):   "0177",
149	strings.ToLower("StreamLocalBindUnlink"): "no",
150	strings.ToLower("StrictHostKeyChecking"): "ask",
151	strings.ToLower("TCPKeepAlive"):          "yes",
152	strings.ToLower("Tunnel"):                "no",
153	strings.ToLower("TunnelDevice"):          "any:any",
154	strings.ToLower("UpdateHostKeys"):        "no",
155	strings.ToLower("UseKeychain"):           "no",
156	strings.ToLower("UsePrivilegedPort"):     "no",
157
158	strings.ToLower("UserKnownHostsFile"): "~/.ssh/known_hosts ~/.ssh/known_hosts2",
159	strings.ToLower("VerifyHostKeyDNS"):   "no",
160	strings.ToLower("VisualHostKey"):      "no",
161	strings.ToLower("XAuthLocation"):      "/usr/X11R6/bin/xauth",
162}
163
164// these identities are used for SSH protocol 2
165var defaultProtocol2Identities = []string{
166	"~/.ssh/id_dsa",
167	"~/.ssh/id_ecdsa",
168	"~/.ssh/id_ed25519",
169	"~/.ssh/id_rsa",
170}
171
172// these directives support multiple items that can be collected
173// across multiple files
174var pluralDirectives = map[string]bool{
175	"CertificateFile": true,
176	"IdentityFile":    true,
177	"DynamicForward":  true,
178	"RemoteForward":   true,
179	"SendEnv":         true,
180	"SetEnv":          true,
181}
182
183// SupportsMultiple reports whether a directive can be specified multiple times.
184func SupportsMultiple(key string) bool {
185	return pluralDirectives[strings.ToLower(key)]
186}