diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/ssh/common.go')
-rw-r--r-- | vendor/golang.org/x/crypto/ssh/common.go | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/ssh/common.go b/vendor/golang.org/x/crypto/ssh/common.go new file mode 100644 index 0000000..8656d0f --- /dev/null +++ b/vendor/golang.org/x/crypto/ssh/common.go | |||
@@ -0,0 +1,371 @@ | |||
1 | // Copyright 2011 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package ssh | ||
6 | |||
7 | import ( | ||
8 | "crypto" | ||
9 | "crypto/rand" | ||
10 | "fmt" | ||
11 | "io" | ||
12 | "sync" | ||
13 | |||
14 | _ "crypto/sha1" | ||
15 | _ "crypto/sha256" | ||
16 | _ "crypto/sha512" | ||
17 | ) | ||
18 | |||
19 | // These are string constants in the SSH protocol. | ||
20 | const ( | ||
21 | compressionNone = "none" | ||
22 | serviceUserAuth = "ssh-userauth" | ||
23 | serviceSSH = "ssh-connection" | ||
24 | ) | ||
25 | |||
26 | // supportedCiphers specifies the supported ciphers in preference order. | ||
27 | var supportedCiphers = []string{ | ||
28 | "aes128-ctr", "aes192-ctr", "aes256-ctr", | ||
29 | "aes128-gcm@openssh.com", | ||
30 | "arcfour256", "arcfour128", | ||
31 | } | ||
32 | |||
33 | // supportedKexAlgos specifies the supported key-exchange algorithms in | ||
34 | // preference order. | ||
35 | var supportedKexAlgos = []string{ | ||
36 | kexAlgoCurve25519SHA256, | ||
37 | // P384 and P521 are not constant-time yet, but since we don't | ||
38 | // reuse ephemeral keys, using them for ECDH should be OK. | ||
39 | kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521, | ||
40 | kexAlgoDH14SHA1, kexAlgoDH1SHA1, | ||
41 | } | ||
42 | |||
43 | // supportedKexAlgos specifies the supported host-key algorithms (i.e. methods | ||
44 | // of authenticating servers) in preference order. | ||
45 | var supportedHostKeyAlgos = []string{ | ||
46 | CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, | ||
47 | CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01, | ||
48 | |||
49 | KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521, | ||
50 | KeyAlgoRSA, KeyAlgoDSA, | ||
51 | |||
52 | KeyAlgoED25519, | ||
53 | } | ||
54 | |||
55 | // supportedMACs specifies a default set of MAC algorithms in preference order. | ||
56 | // This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed | ||
57 | // because they have reached the end of their useful life. | ||
58 | var supportedMACs = []string{ | ||
59 | "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96", | ||
60 | } | ||
61 | |||
62 | var supportedCompressions = []string{compressionNone} | ||
63 | |||
64 | // hashFuncs keeps the mapping of supported algorithms to their respective | ||
65 | // hashes needed for signature verification. | ||
66 | var hashFuncs = map[string]crypto.Hash{ | ||
67 | KeyAlgoRSA: crypto.SHA1, | ||
68 | KeyAlgoDSA: crypto.SHA1, | ||
69 | KeyAlgoECDSA256: crypto.SHA256, | ||
70 | KeyAlgoECDSA384: crypto.SHA384, | ||
71 | KeyAlgoECDSA521: crypto.SHA512, | ||
72 | CertAlgoRSAv01: crypto.SHA1, | ||
73 | CertAlgoDSAv01: crypto.SHA1, | ||
74 | CertAlgoECDSA256v01: crypto.SHA256, | ||
75 | CertAlgoECDSA384v01: crypto.SHA384, | ||
76 | CertAlgoECDSA521v01: crypto.SHA512, | ||
77 | } | ||
78 | |||
79 | // unexpectedMessageError results when the SSH message that we received didn't | ||
80 | // match what we wanted. | ||
81 | func unexpectedMessageError(expected, got uint8) error { | ||
82 | return fmt.Errorf("ssh: unexpected message type %d (expected %d)", got, expected) | ||
83 | } | ||
84 | |||
85 | // parseError results from a malformed SSH message. | ||
86 | func parseError(tag uint8) error { | ||
87 | return fmt.Errorf("ssh: parse error in message type %d", tag) | ||
88 | } | ||
89 | |||
90 | func findCommon(what string, client []string, server []string) (common string, err error) { | ||
91 | for _, c := range client { | ||
92 | for _, s := range server { | ||
93 | if c == s { | ||
94 | return c, nil | ||
95 | } | ||
96 | } | ||
97 | } | ||
98 | return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) | ||
99 | } | ||
100 | |||
101 | type directionAlgorithms struct { | ||
102 | Cipher string | ||
103 | MAC string | ||
104 | Compression string | ||
105 | } | ||
106 | |||
107 | // rekeyBytes returns a rekeying intervals in bytes. | ||
108 | func (a *directionAlgorithms) rekeyBytes() int64 { | ||
109 | // According to RFC4344 block ciphers should rekey after | ||
110 | // 2^(BLOCKSIZE/4) blocks. For all AES flavors BLOCKSIZE is | ||
111 | // 128. | ||
112 | switch a.Cipher { | ||
113 | case "aes128-ctr", "aes192-ctr", "aes256-ctr", gcmCipherID, aes128cbcID: | ||
114 | return 16 * (1 << 32) | ||
115 | |||
116 | } | ||
117 | |||
118 | // For others, stick with RFC4253 recommendation to rekey after 1 Gb of data. | ||
119 | return 1 << 30 | ||
120 | } | ||
121 | |||
122 | type algorithms struct { | ||
123 | kex string | ||
124 | hostKey string | ||
125 | w directionAlgorithms | ||
126 | r directionAlgorithms | ||
127 | } | ||
128 | |||
129 | func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { | ||
130 | result := &algorithms{} | ||
131 | |||
132 | result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) | ||
133 | if err != nil { | ||
134 | return | ||
135 | } | ||
136 | |||
137 | result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) | ||
138 | if err != nil { | ||
139 | return | ||
140 | } | ||
141 | |||
142 | result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) | ||
143 | if err != nil { | ||
144 | return | ||
145 | } | ||
146 | |||
147 | result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) | ||
148 | if err != nil { | ||
149 | return | ||
150 | } | ||
151 | |||
152 | result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) | ||
153 | if err != nil { | ||
154 | return | ||
155 | } | ||
156 | |||
157 | result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) | ||
158 | if err != nil { | ||
159 | return | ||
160 | } | ||
161 | |||
162 | result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) | ||
163 | if err != nil { | ||
164 | return | ||
165 | } | ||
166 | |||
167 | result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) | ||
168 | if err != nil { | ||
169 | return | ||
170 | } | ||
171 | |||
172 | return result, nil | ||
173 | } | ||
174 | |||
175 | // If rekeythreshold is too small, we can't make any progress sending | ||
176 | // stuff. | ||
177 | const minRekeyThreshold uint64 = 256 | ||
178 | |||
179 | // Config contains configuration data common to both ServerConfig and | ||
180 | // ClientConfig. | ||
181 | type Config struct { | ||
182 | // Rand provides the source of entropy for cryptographic | ||
183 | // primitives. If Rand is nil, the cryptographic random reader | ||
184 | // in package crypto/rand will be used. | ||
185 | Rand io.Reader | ||
186 | |||
187 | // The maximum number of bytes sent or received after which a | ||
188 | // new key is negotiated. It must be at least 256. If | ||
189 | // unspecified, 1 gigabyte is used. | ||
190 | RekeyThreshold uint64 | ||
191 | |||
192 | // The allowed key exchanges algorithms. If unspecified then a | ||
193 | // default set of algorithms is used. | ||
194 | KeyExchanges []string | ||
195 | |||
196 | // The allowed cipher algorithms. If unspecified then a sensible | ||
197 | // default is used. | ||
198 | Ciphers []string | ||
199 | |||
200 | // The allowed MAC algorithms. If unspecified then a sensible default | ||
201 | // is used. | ||
202 | MACs []string | ||
203 | } | ||
204 | |||
205 | // SetDefaults sets sensible values for unset fields in config. This is | ||
206 | // exported for testing: Configs passed to SSH functions are copied and have | ||
207 | // default values set automatically. | ||
208 | func (c *Config) SetDefaults() { | ||
209 | if c.Rand == nil { | ||
210 | c.Rand = rand.Reader | ||
211 | } | ||
212 | if c.Ciphers == nil { | ||
213 | c.Ciphers = supportedCiphers | ||
214 | } | ||
215 | var ciphers []string | ||
216 | for _, c := range c.Ciphers { | ||
217 | if cipherModes[c] != nil { | ||
218 | // reject the cipher if we have no cipherModes definition | ||
219 | ciphers = append(ciphers, c) | ||
220 | } | ||
221 | } | ||
222 | c.Ciphers = ciphers | ||
223 | |||
224 | if c.KeyExchanges == nil { | ||
225 | c.KeyExchanges = supportedKexAlgos | ||
226 | } | ||
227 | |||
228 | if c.MACs == nil { | ||
229 | c.MACs = supportedMACs | ||
230 | } | ||
231 | |||
232 | if c.RekeyThreshold == 0 { | ||
233 | // RFC 4253, section 9 suggests rekeying after 1G. | ||
234 | c.RekeyThreshold = 1 << 30 | ||
235 | } | ||
236 | if c.RekeyThreshold < minRekeyThreshold { | ||
237 | c.RekeyThreshold = minRekeyThreshold | ||
238 | } | ||
239 | } | ||
240 | |||
241 | // buildDataSignedForAuth returns the data that is signed in order to prove | ||
242 | // possession of a private key. See RFC 4252, section 7. | ||
243 | func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { | ||
244 | data := struct { | ||
245 | Session []byte | ||
246 | Type byte | ||
247 | User string | ||
248 | Service string | ||
249 | Method string | ||
250 | Sign bool | ||
251 | Algo []byte | ||
252 | PubKey []byte | ||
253 | }{ | ||
254 | sessionId, | ||
255 | msgUserAuthRequest, | ||
256 | req.User, | ||
257 | req.Service, | ||
258 | req.Method, | ||
259 | true, | ||
260 | algo, | ||
261 | pubKey, | ||
262 | } | ||
263 | return Marshal(data) | ||
264 | } | ||
265 | |||
266 | func appendU16(buf []byte, n uint16) []byte { | ||
267 | return append(buf, byte(n>>8), byte(n)) | ||
268 | } | ||
269 | |||
270 | func appendU32(buf []byte, n uint32) []byte { | ||
271 | return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) | ||
272 | } | ||
273 | |||
274 | func appendU64(buf []byte, n uint64) []byte { | ||
275 | return append(buf, | ||
276 | byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), | ||
277 | byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) | ||
278 | } | ||
279 | |||
280 | func appendInt(buf []byte, n int) []byte { | ||
281 | return appendU32(buf, uint32(n)) | ||
282 | } | ||
283 | |||
284 | func appendString(buf []byte, s string) []byte { | ||
285 | buf = appendU32(buf, uint32(len(s))) | ||
286 | buf = append(buf, s...) | ||
287 | return buf | ||
288 | } | ||
289 | |||
290 | func appendBool(buf []byte, b bool) []byte { | ||
291 | if b { | ||
292 | return append(buf, 1) | ||
293 | } | ||
294 | return append(buf, 0) | ||
295 | } | ||
296 | |||
297 | // newCond is a helper to hide the fact that there is no usable zero | ||
298 | // value for sync.Cond. | ||
299 | func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } | ||
300 | |||
301 | // window represents the buffer available to clients | ||
302 | // wishing to write to a channel. | ||
303 | type window struct { | ||
304 | *sync.Cond | ||
305 | win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 | ||
306 | writeWaiters int | ||
307 | closed bool | ||
308 | } | ||
309 | |||
310 | // add adds win to the amount of window available | ||
311 | // for consumers. | ||
312 | func (w *window) add(win uint32) bool { | ||
313 | // a zero sized window adjust is a noop. | ||
314 | if win == 0 { | ||
315 | return true | ||
316 | } | ||
317 | w.L.Lock() | ||
318 | if w.win+win < win { | ||
319 | w.L.Unlock() | ||
320 | return false | ||
321 | } | ||
322 | w.win += win | ||
323 | // It is unusual that multiple goroutines would be attempting to reserve | ||
324 | // window space, but not guaranteed. Use broadcast to notify all waiters | ||
325 | // that additional window is available. | ||
326 | w.Broadcast() | ||
327 | w.L.Unlock() | ||
328 | return true | ||
329 | } | ||
330 | |||
331 | // close sets the window to closed, so all reservations fail | ||
332 | // immediately. | ||
333 | func (w *window) close() { | ||
334 | w.L.Lock() | ||
335 | w.closed = true | ||
336 | w.Broadcast() | ||
337 | w.L.Unlock() | ||
338 | } | ||
339 | |||
340 | // reserve reserves win from the available window capacity. | ||
341 | // If no capacity remains, reserve will block. reserve may | ||
342 | // return less than requested. | ||
343 | func (w *window) reserve(win uint32) (uint32, error) { | ||
344 | var err error | ||
345 | w.L.Lock() | ||
346 | w.writeWaiters++ | ||
347 | w.Broadcast() | ||
348 | for w.win == 0 && !w.closed { | ||
349 | w.Wait() | ||
350 | } | ||
351 | w.writeWaiters-- | ||
352 | if w.win < win { | ||
353 | win = w.win | ||
354 | } | ||
355 | w.win -= win | ||
356 | if w.closed { | ||
357 | err = io.EOF | ||
358 | } | ||
359 | w.L.Unlock() | ||
360 | return win, err | ||
361 | } | ||
362 | |||
363 | // waitWriterBlocked waits until some goroutine is blocked for further | ||
364 | // writes. It is used in tests only. | ||
365 | func (w *window) waitWriterBlocked() { | ||
366 | w.Cond.L.Lock() | ||
367 | for w.writeWaiters == 0 { | ||
368 | w.Cond.Wait() | ||
369 | } | ||
370 | w.Cond.L.Unlock() | ||
371 | } | ||