github.com/maenmax/kairep@v0.0.0-20210218001208-55bf3df36788/src/golang.org/x/crypto/ssh/common.go (about) 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", "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 type algorithms struct { 108 kex string 109 hostKey string 110 w directionAlgorithms 111 r directionAlgorithms 112 } 113 114 func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { 115 result := &algorithms{} 116 117 result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) 118 if err != nil { 119 return 120 } 121 122 result.hostKey, err = findCommon("host key", clientKexInit.ServerHostKeyAlgos, serverKexInit.ServerHostKeyAlgos) 123 if err != nil { 124 return 125 } 126 127 result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) 128 if err != nil { 129 return 130 } 131 132 result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) 133 if err != nil { 134 return 135 } 136 137 result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) 138 if err != nil { 139 return 140 } 141 142 result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) 143 if err != nil { 144 return 145 } 146 147 result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) 148 if err != nil { 149 return 150 } 151 152 result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) 153 if err != nil { 154 return 155 } 156 157 return result, nil 158 } 159 160 // If rekeythreshold is too small, we can't make any progress sending 161 // stuff. 162 const minRekeyThreshold uint64 = 256 163 164 // Config contains configuration data common to both ServerConfig and 165 // ClientConfig. 166 type Config struct { 167 // Rand provides the source of entropy for cryptographic 168 // primitives. If Rand is nil, the cryptographic random reader 169 // in package crypto/rand will be used. 170 Rand io.Reader 171 172 // The maximum number of bytes sent or received after which a 173 // new key is negotiated. It must be at least 256. If 174 // unspecified, 1 gigabyte is used. 175 RekeyThreshold uint64 176 177 // The allowed key exchanges algorithms. If unspecified then a 178 // default set of algorithms is used. 179 KeyExchanges []string 180 181 // The allowed cipher algorithms. If unspecified then a sensible 182 // default is used. 183 Ciphers []string 184 185 // The allowed MAC algorithms. If unspecified then a sensible default 186 // is used. 187 MACs []string 188 } 189 190 // SetDefaults sets sensible values for unset fields in config. This is 191 // exported for testing: Configs passed to SSH functions are copied and have 192 // default values set automatically. 193 func (c *Config) SetDefaults() { 194 if c.Rand == nil { 195 c.Rand = rand.Reader 196 } 197 if c.Ciphers == nil { 198 c.Ciphers = supportedCiphers 199 } 200 var ciphers []string 201 for _, c := range c.Ciphers { 202 if cipherModes[c] != nil { 203 // reject the cipher if we have no cipherModes definition 204 ciphers = append(ciphers, c) 205 } 206 } 207 c.Ciphers = ciphers 208 209 if c.KeyExchanges == nil { 210 c.KeyExchanges = supportedKexAlgos 211 } 212 213 if c.MACs == nil { 214 c.MACs = supportedMACs 215 } 216 217 if c.RekeyThreshold == 0 { 218 // RFC 4253, section 9 suggests rekeying after 1G. 219 c.RekeyThreshold = 1 << 30 220 } 221 if c.RekeyThreshold < minRekeyThreshold { 222 c.RekeyThreshold = minRekeyThreshold 223 } 224 } 225 226 // buildDataSignedForAuth returns the data that is signed in order to prove 227 // possession of a private key. See RFC 4252, section 7. 228 func buildDataSignedForAuth(sessionId []byte, req userAuthRequestMsg, algo, pubKey []byte) []byte { 229 data := struct { 230 Session []byte 231 Type byte 232 User string 233 Service string 234 Method string 235 Sign bool 236 Algo []byte 237 PubKey []byte 238 }{ 239 sessionId, 240 msgUserAuthRequest, 241 req.User, 242 req.Service, 243 req.Method, 244 true, 245 algo, 246 pubKey, 247 } 248 return Marshal(data) 249 } 250 251 func appendU16(buf []byte, n uint16) []byte { 252 return append(buf, byte(n>>8), byte(n)) 253 } 254 255 func appendU32(buf []byte, n uint32) []byte { 256 return append(buf, byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) 257 } 258 259 func appendU64(buf []byte, n uint64) []byte { 260 return append(buf, 261 byte(n>>56), byte(n>>48), byte(n>>40), byte(n>>32), 262 byte(n>>24), byte(n>>16), byte(n>>8), byte(n)) 263 } 264 265 func appendInt(buf []byte, n int) []byte { 266 return appendU32(buf, uint32(n)) 267 } 268 269 func appendString(buf []byte, s string) []byte { 270 buf = appendU32(buf, uint32(len(s))) 271 buf = append(buf, s...) 272 return buf 273 } 274 275 func appendBool(buf []byte, b bool) []byte { 276 if b { 277 return append(buf, 1) 278 } 279 return append(buf, 0) 280 } 281 282 // newCond is a helper to hide the fact that there is no usable zero 283 // value for sync.Cond. 284 func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) } 285 286 // window represents the buffer available to clients 287 // wishing to write to a channel. 288 type window struct { 289 *sync.Cond 290 win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1 291 writeWaiters int 292 closed bool 293 } 294 295 // add adds win to the amount of window available 296 // for consumers. 297 func (w *window) add(win uint32) bool { 298 // a zero sized window adjust is a noop. 299 if win == 0 { 300 return true 301 } 302 w.L.Lock() 303 if w.win+win < win { 304 w.L.Unlock() 305 return false 306 } 307 w.win += win 308 // It is unusual that multiple goroutines would be attempting to reserve 309 // window space, but not guaranteed. Use broadcast to notify all waiters 310 // that additional window is available. 311 w.Broadcast() 312 w.L.Unlock() 313 return true 314 } 315 316 // close sets the window to closed, so all reservations fail 317 // immediately. 318 func (w *window) close() { 319 w.L.Lock() 320 w.closed = true 321 w.Broadcast() 322 w.L.Unlock() 323 } 324 325 // reserve reserves win from the available window capacity. 326 // If no capacity remains, reserve will block. reserve may 327 // return less than requested. 328 func (w *window) reserve(win uint32) (uint32, error) { 329 var err error 330 w.L.Lock() 331 w.writeWaiters++ 332 w.Broadcast() 333 for w.win == 0 && !w.closed { 334 w.Wait() 335 } 336 w.writeWaiters-- 337 if w.win < win { 338 win = w.win 339 } 340 w.win -= win 341 if w.closed { 342 err = io.EOF 343 } 344 w.L.Unlock() 345 return win, err 346 } 347 348 // waitWriterBlocked waits until some goroutine is blocked for further 349 // writes. It is used in tests only. 350 func (w *window) waitWriterBlocked() { 351 w.Cond.L.Lock() 352 for w.writeWaiters == 0 { 353 w.Cond.Wait() 354 } 355 w.Cond.L.Unlock() 356 }