~cloud-green/juju-core/charmstore-sdist

« back to all changes in this revision

Viewing changes to code.google.com/p/go.crypto/ssh/server.go

  • Committer: Casey Marshall
  • Date: 2014-03-27 15:59:46 UTC
  • Revision ID: cmars@cmarstech.com-20140327155946-8huorf37g0zwar43
Source distribution of launchpad.net/juju-core created 20140327105939

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        "bytes"
 
9
        "crypto/rand"
 
10
        "encoding/binary"
 
11
        "errors"
 
12
        "fmt"
 
13
        "io"
 
14
        "net"
 
15
        "sync"
 
16
 
 
17
        _ "crypto/sha1"
 
18
)
 
19
 
 
20
type ServerConfig struct {
 
21
        hostKeys []Signer
 
22
 
 
23
        // Rand provides the source of entropy for key exchange. If Rand is
 
24
        // nil, the cryptographic random reader in package crypto/rand will
 
25
        // be used.
 
26
        Rand io.Reader
 
27
 
 
28
        // NoClientAuth is true if clients are allowed to connect without
 
29
        // authenticating.
 
30
        NoClientAuth bool
 
31
 
 
32
        // PasswordCallback, if non-nil, is called when a user attempts to
 
33
        // authenticate using a password. It may be called concurrently from
 
34
        // several goroutines.
 
35
        PasswordCallback func(conn *ServerConn, user, password string) bool
 
36
 
 
37
        // PublicKeyCallback, if non-nil, is called when a client attempts public
 
38
        // key authentication. It must return true if the given public key is
 
39
        // valid for the given user.
 
40
        PublicKeyCallback func(conn *ServerConn, user, algo string, pubkey []byte) bool
 
41
 
 
42
        // KeyboardInteractiveCallback, if non-nil, is called when
 
43
        // keyboard-interactive authentication is selected (RFC
 
44
        // 4256). The client object's Challenge function should be
 
45
        // used to query the user. The callback may offer multiple
 
46
        // Challenge rounds. To avoid information leaks, the client
 
47
        // should be presented a challenge even if the user is
 
48
        // unknown.
 
49
        KeyboardInteractiveCallback func(conn *ServerConn, user string, client ClientKeyboardInteractive) bool
 
50
 
 
51
        // Cryptographic-related configuration.
 
52
        Crypto CryptoConfig
 
53
}
 
54
 
 
55
func (c *ServerConfig) rand() io.Reader {
 
56
        if c.Rand == nil {
 
57
                return rand.Reader
 
58
        }
 
59
        return c.Rand
 
60
}
 
61
 
 
62
// AddHostKey adds a private key as a host key. If an existing host
 
63
// key exists with the same algorithm, it is overwritten.
 
64
func (s *ServerConfig) AddHostKey(key Signer) {
 
65
        for i, k := range s.hostKeys {
 
66
                if k.PublicKey().PublicKeyAlgo() == key.PublicKey().PublicKeyAlgo() {
 
67
                        s.hostKeys[i] = key
 
68
                        return
 
69
                }
 
70
        }
 
71
 
 
72
        s.hostKeys = append(s.hostKeys, key)
 
73
}
 
74
 
 
75
// SetRSAPrivateKey sets the private key for a Server. A Server must have a
 
76
// private key configured in order to accept connections. The private key must
 
77
// be in the form of a PEM encoded, PKCS#1, RSA private key. The file "id_rsa"
 
78
// typically contains such a key.
 
79
func (s *ServerConfig) SetRSAPrivateKey(pemBytes []byte) error {
 
80
        priv, err := ParsePrivateKey(pemBytes)
 
81
        if err != nil {
 
82
                return err
 
83
        }
 
84
        s.AddHostKey(priv)
 
85
        return nil
 
86
}
 
87
 
 
88
// cachedPubKey contains the results of querying whether a public key is
 
89
// acceptable for a user. The cache only applies to a single ServerConn.
 
90
type cachedPubKey struct {
 
91
        user, algo string
 
92
        pubKey     []byte
 
93
        result     bool
 
94
}
 
95
 
 
96
const maxCachedPubKeys = 16
 
97
 
 
98
// A ServerConn represents an incoming connection.
 
99
type ServerConn struct {
 
100
        transport *transport
 
101
        config    *ServerConfig
 
102
 
 
103
        channels   map[uint32]*serverChan
 
104
        nextChanId uint32
 
105
 
 
106
        // lock protects err and channels.
 
107
        lock sync.Mutex
 
108
        err  error
 
109
 
 
110
        // cachedPubKeys contains the cache results of tests for public keys.
 
111
        // Since SSH clients will query whether a public key is acceptable
 
112
        // before attempting to authenticate with it, we end up with duplicate
 
113
        // queries for public key validity.
 
114
        cachedPubKeys []cachedPubKey
 
115
 
 
116
        // User holds the successfully authenticated user name.
 
117
        // It is empty if no authentication is used.  It is populated before
 
118
        // any authentication callback is called and not assigned to after that.
 
119
        User string
 
120
 
 
121
        // ClientVersion is the client's version, populated after
 
122
        // Handshake is called. It should not be modified.
 
123
        ClientVersion []byte
 
124
 
 
125
        // Our version.
 
126
        serverVersion []byte
 
127
}
 
128
 
 
129
// Server returns a new SSH server connection
 
130
// using c as the underlying transport.
 
131
func Server(c net.Conn, config *ServerConfig) *ServerConn {
 
132
        return &ServerConn{
 
133
                transport: newTransport(c, config.rand(), false /* not client */),
 
134
                channels:  make(map[uint32]*serverChan),
 
135
                config:    config,
 
136
        }
 
137
}
 
138
 
 
139
// signAndMarshal signs the data with the appropriate algorithm,
 
140
// and serializes the result in SSH wire format.
 
141
func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
 
142
        sig, err := k.Sign(rand, data)
 
143
        if err != nil {
 
144
                return nil, err
 
145
        }
 
146
 
 
147
        return serializeSignature(k.PublicKey().PrivateKeyAlgo(), sig), nil
 
148
}
 
149
 
 
150
// Close closes the connection.
 
151
func (s *ServerConn) Close() error { return s.transport.Close() }
 
152
 
 
153
// LocalAddr returns the local network address.
 
154
func (c *ServerConn) LocalAddr() net.Addr { return c.transport.LocalAddr() }
 
155
 
 
156
// RemoteAddr returns the remote network address.
 
157
func (c *ServerConn) RemoteAddr() net.Addr { return c.transport.RemoteAddr() }
 
158
 
 
159
// Handshake performs an SSH transport and client authentication on the given ServerConn.
 
160
func (s *ServerConn) Handshake() error {
 
161
        var err error
 
162
        s.serverVersion = []byte(packageVersion)
 
163
        s.ClientVersion, err = exchangeVersions(s.transport.Conn, s.serverVersion)
 
164
        if err != nil {
 
165
                return err
 
166
        }
 
167
        if err := s.clientInitHandshake(nil, nil); err != nil {
 
168
                return err
 
169
        }
 
170
 
 
171
        var packet []byte
 
172
        if packet, err = s.transport.readPacket(); err != nil {
 
173
                return err
 
174
        }
 
175
        var serviceRequest serviceRequestMsg
 
176
        if err := unmarshal(&serviceRequest, packet, msgServiceRequest); err != nil {
 
177
                return err
 
178
        }
 
179
        if serviceRequest.Service != serviceUserAuth {
 
180
                return errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
 
181
        }
 
182
        serviceAccept := serviceAcceptMsg{
 
183
                Service: serviceUserAuth,
 
184
        }
 
185
        if err := s.transport.writePacket(marshal(msgServiceAccept, serviceAccept)); err != nil {
 
186
                return err
 
187
        }
 
188
 
 
189
        if err := s.authenticate(); err != nil {
 
190
                return err
 
191
        }
 
192
        return err
 
193
}
 
194
 
 
195
func (s *ServerConn) clientInitHandshake(clientKexInit *kexInitMsg, clientKexInitPacket []byte) (err error) {
 
196
        serverKexInit := kexInitMsg{
 
197
                KexAlgos:                s.config.Crypto.kexes(),
 
198
                CiphersClientServer:     s.config.Crypto.ciphers(),
 
199
                CiphersServerClient:     s.config.Crypto.ciphers(),
 
200
                MACsClientServer:        s.config.Crypto.macs(),
 
201
                MACsServerClient:        s.config.Crypto.macs(),
 
202
                CompressionClientServer: supportedCompressions,
 
203
                CompressionServerClient: supportedCompressions,
 
204
        }
 
205
        for _, k := range s.config.hostKeys {
 
206
                serverKexInit.ServerHostKeyAlgos = append(
 
207
                        serverKexInit.ServerHostKeyAlgos, k.PublicKey().PublicKeyAlgo())
 
208
        }
 
209
 
 
210
        serverKexInitPacket := marshal(msgKexInit, serverKexInit)
 
211
        if err = s.transport.writePacket(serverKexInitPacket); err != nil {
 
212
                return
 
213
        }
 
214
 
 
215
        if clientKexInitPacket == nil {
 
216
                clientKexInit = new(kexInitMsg)
 
217
                if clientKexInitPacket, err = s.transport.readPacket(); err != nil {
 
218
                        return
 
219
                }
 
220
                if err = unmarshal(clientKexInit, clientKexInitPacket, msgKexInit); err != nil {
 
221
                        return
 
222
                }
 
223
        }
 
224
 
 
225
        algs := findAgreedAlgorithms(clientKexInit, &serverKexInit)
 
226
        if algs == nil {
 
227
                return errors.New("ssh: no common algorithms")
 
228
        }
 
229
 
 
230
        if clientKexInit.FirstKexFollows && algs.kex != clientKexInit.KexAlgos[0] {
 
231
                // The client sent a Kex message for the wrong algorithm,
 
232
                // which we have to ignore.
 
233
                if _, err = s.transport.readPacket(); err != nil {
 
234
                        return
 
235
                }
 
236
        }
 
237
 
 
238
        var hostKey Signer
 
239
        for _, k := range s.config.hostKeys {
 
240
                if algs.hostKey == k.PublicKey().PublicKeyAlgo() {
 
241
                        hostKey = k
 
242
                }
 
243
        }
 
244
 
 
245
        kex, ok := kexAlgoMap[algs.kex]
 
246
        if !ok {
 
247
                return fmt.Errorf("ssh: unexpected key exchange algorithm %v", algs.kex)
 
248
        }
 
249
 
 
250
        magics := handshakeMagics{
 
251
                serverVersion: s.serverVersion,
 
252
                clientVersion: s.ClientVersion,
 
253
                serverKexInit: marshal(msgKexInit, serverKexInit),
 
254
                clientKexInit: clientKexInitPacket,
 
255
        }
 
256
        result, err := kex.Server(s.transport, s.config.rand(), &magics, hostKey)
 
257
        if err != nil {
 
258
                return err
 
259
        }
 
260
 
 
261
        if err = s.transport.prepareKeyChange(algs, result); err != nil {
 
262
                return err
 
263
        }
 
264
 
 
265
        if err = s.transport.writePacket([]byte{msgNewKeys}); err != nil {
 
266
                return
 
267
        }
 
268
        if packet, err := s.transport.readPacket(); err != nil {
 
269
                return err
 
270
        } else if packet[0] != msgNewKeys {
 
271
                return UnexpectedMessageError{msgNewKeys, packet[0]}
 
272
        }
 
273
 
 
274
        return
 
275
}
 
276
 
 
277
func isAcceptableAlgo(algo string) bool {
 
278
        switch algo {
 
279
        case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
 
280
                CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECDSA384v01, CertAlgoECDSA521v01:
 
281
                return true
 
282
        }
 
283
        return false
 
284
}
 
285
 
 
286
// testPubKey returns true if the given public key is acceptable for the user.
 
287
func (s *ServerConn) testPubKey(user, algo string, pubKey []byte) bool {
 
288
        if s.config.PublicKeyCallback == nil || !isAcceptableAlgo(algo) {
 
289
                return false
 
290
        }
 
291
 
 
292
        for _, c := range s.cachedPubKeys {
 
293
                if c.user == user && c.algo == algo && bytes.Equal(c.pubKey, pubKey) {
 
294
                        return c.result
 
295
                }
 
296
        }
 
297
 
 
298
        result := s.config.PublicKeyCallback(s, user, algo, pubKey)
 
299
        if len(s.cachedPubKeys) < maxCachedPubKeys {
 
300
                c := cachedPubKey{
 
301
                        user:   user,
 
302
                        algo:   algo,
 
303
                        pubKey: make([]byte, len(pubKey)),
 
304
                        result: result,
 
305
                }
 
306
                copy(c.pubKey, pubKey)
 
307
                s.cachedPubKeys = append(s.cachedPubKeys, c)
 
308
        }
 
309
 
 
310
        return result
 
311
}
 
312
 
 
313
func (s *ServerConn) authenticate() error {
 
314
        var userAuthReq userAuthRequestMsg
 
315
        var err error
 
316
        var packet []byte
 
317
 
 
318
userAuthLoop:
 
319
        for {
 
320
                if packet, err = s.transport.readPacket(); err != nil {
 
321
                        return err
 
322
                }
 
323
                if err = unmarshal(&userAuthReq, packet, msgUserAuthRequest); err != nil {
 
324
                        return err
 
325
                }
 
326
 
 
327
                if userAuthReq.Service != serviceSSH {
 
328
                        return errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
 
329
                }
 
330
 
 
331
                switch userAuthReq.Method {
 
332
                case "none":
 
333
                        if s.config.NoClientAuth {
 
334
                                break userAuthLoop
 
335
                        }
 
336
                case "password":
 
337
                        if s.config.PasswordCallback == nil {
 
338
                                break
 
339
                        }
 
340
                        payload := userAuthReq.Payload
 
341
                        if len(payload) < 1 || payload[0] != 0 {
 
342
                                return ParseError{msgUserAuthRequest}
 
343
                        }
 
344
                        payload = payload[1:]
 
345
                        password, payload, ok := parseString(payload)
 
346
                        if !ok || len(payload) > 0 {
 
347
                                return ParseError{msgUserAuthRequest}
 
348
                        }
 
349
 
 
350
                        s.User = userAuthReq.User
 
351
                        if s.config.PasswordCallback(s, userAuthReq.User, string(password)) {
 
352
                                break userAuthLoop
 
353
                        }
 
354
                case "keyboard-interactive":
 
355
                        if s.config.KeyboardInteractiveCallback == nil {
 
356
                                break
 
357
                        }
 
358
 
 
359
                        s.User = userAuthReq.User
 
360
                        if s.config.KeyboardInteractiveCallback(s, s.User, &sshClientKeyboardInteractive{s}) {
 
361
                                break userAuthLoop
 
362
                        }
 
363
                case "publickey":
 
364
                        if s.config.PublicKeyCallback == nil {
 
365
                                break
 
366
                        }
 
367
                        payload := userAuthReq.Payload
 
368
                        if len(payload) < 1 {
 
369
                                return ParseError{msgUserAuthRequest}
 
370
                        }
 
371
                        isQuery := payload[0] == 0
 
372
                        payload = payload[1:]
 
373
                        algoBytes, payload, ok := parseString(payload)
 
374
                        if !ok {
 
375
                                return ParseError{msgUserAuthRequest}
 
376
                        }
 
377
                        algo := string(algoBytes)
 
378
 
 
379
                        pubKey, payload, ok := parseString(payload)
 
380
                        if !ok {
 
381
                                return ParseError{msgUserAuthRequest}
 
382
                        }
 
383
                        if isQuery {
 
384
                                // The client can query if the given public key
 
385
                                // would be okay.
 
386
                                if len(payload) > 0 {
 
387
                                        return ParseError{msgUserAuthRequest}
 
388
                                }
 
389
                                if s.testPubKey(userAuthReq.User, algo, pubKey) {
 
390
                                        okMsg := userAuthPubKeyOkMsg{
 
391
                                                Algo:   algo,
 
392
                                                PubKey: string(pubKey),
 
393
                                        }
 
394
                                        if err = s.transport.writePacket(marshal(msgUserAuthPubKeyOk, okMsg)); err != nil {
 
395
                                                return err
 
396
                                        }
 
397
                                        continue userAuthLoop
 
398
                                }
 
399
                        } else {
 
400
                                sig, payload, ok := parseSignature(payload)
 
401
                                if !ok || len(payload) > 0 {
 
402
                                        return ParseError{msgUserAuthRequest}
 
403
                                }
 
404
                                // Ensure the public key algo and signature algo
 
405
                                // are supported.  Compare the private key
 
406
                                // algorithm name that corresponds to algo with
 
407
                                // sig.Format.  This is usually the same, but
 
408
                                // for certs, the names differ.
 
409
                                if !isAcceptableAlgo(algo) || !isAcceptableAlgo(sig.Format) || pubAlgoToPrivAlgo(algo) != sig.Format {
 
410
                                        break
 
411
                                }
 
412
                                signedData := buildDataSignedForAuth(s.transport.sessionID, userAuthReq, algoBytes, pubKey)
 
413
                                key, _, ok := ParsePublicKey(pubKey)
 
414
                                if !ok {
 
415
                                        return ParseError{msgUserAuthRequest}
 
416
                                }
 
417
 
 
418
                                if !key.Verify(signedData, sig.Blob) {
 
419
                                        return ParseError{msgUserAuthRequest}
 
420
                                }
 
421
                                // TODO(jmpittman): Implement full validation for certificates.
 
422
                                s.User = userAuthReq.User
 
423
                                if s.testPubKey(userAuthReq.User, algo, pubKey) {
 
424
                                        break userAuthLoop
 
425
                                }
 
426
                        }
 
427
                }
 
428
 
 
429
                var failureMsg userAuthFailureMsg
 
430
                if s.config.PasswordCallback != nil {
 
431
                        failureMsg.Methods = append(failureMsg.Methods, "password")
 
432
                }
 
433
                if s.config.PublicKeyCallback != nil {
 
434
                        failureMsg.Methods = append(failureMsg.Methods, "publickey")
 
435
                }
 
436
                if s.config.KeyboardInteractiveCallback != nil {
 
437
                        failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
 
438
                }
 
439
 
 
440
                if len(failureMsg.Methods) == 0 {
 
441
                        return errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
 
442
                }
 
443
 
 
444
                if err = s.transport.writePacket(marshal(msgUserAuthFailure, failureMsg)); err != nil {
 
445
                        return err
 
446
                }
 
447
        }
 
448
 
 
449
        packet = []byte{msgUserAuthSuccess}
 
450
        if err = s.transport.writePacket(packet); err != nil {
 
451
                return err
 
452
        }
 
453
 
 
454
        return nil
 
455
}
 
456
 
 
457
// sshClientKeyboardInteractive implements a ClientKeyboardInteractive by
 
458
// asking the client on the other side of a ServerConn.
 
459
type sshClientKeyboardInteractive struct {
 
460
        *ServerConn
 
461
}
 
462
 
 
463
func (c *sshClientKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
 
464
        if len(questions) != len(echos) {
 
465
                return nil, errors.New("ssh: echos and questions must have equal length")
 
466
        }
 
467
 
 
468
        var prompts []byte
 
469
        for i := range questions {
 
470
                prompts = appendString(prompts, questions[i])
 
471
                prompts = appendBool(prompts, echos[i])
 
472
        }
 
473
 
 
474
        if err := c.transport.writePacket(marshal(msgUserAuthInfoRequest, userAuthInfoRequestMsg{
 
475
                Instruction: instruction,
 
476
                NumPrompts:  uint32(len(questions)),
 
477
                Prompts:     prompts,
 
478
        })); err != nil {
 
479
                return nil, err
 
480
        }
 
481
 
 
482
        packet, err := c.transport.readPacket()
 
483
        if err != nil {
 
484
                return nil, err
 
485
        }
 
486
        if packet[0] != msgUserAuthInfoResponse {
 
487
                return nil, UnexpectedMessageError{msgUserAuthInfoResponse, packet[0]}
 
488
        }
 
489
        packet = packet[1:]
 
490
 
 
491
        n, packet, ok := parseUint32(packet)
 
492
        if !ok || int(n) != len(questions) {
 
493
                return nil, &ParseError{msgUserAuthInfoResponse}
 
494
        }
 
495
 
 
496
        for i := uint32(0); i < n; i++ {
 
497
                ans, rest, ok := parseString(packet)
 
498
                if !ok {
 
499
                        return nil, &ParseError{msgUserAuthInfoResponse}
 
500
                }
 
501
 
 
502
                answers = append(answers, string(ans))
 
503
                packet = rest
 
504
        }
 
505
        if len(packet) != 0 {
 
506
                return nil, errors.New("ssh: junk at end of message")
 
507
        }
 
508
 
 
509
        return answers, nil
 
510
}
 
511
 
 
512
const defaultWindowSize = 32768
 
513
 
 
514
// Accept reads and processes messages on a ServerConn. It must be called
 
515
// in order to demultiplex messages to any resulting Channels.
 
516
func (s *ServerConn) Accept() (Channel, error) {
 
517
        // TODO(dfc) s.lock is not held here so visibility of s.err is not guaranteed.
 
518
        if s.err != nil {
 
519
                return nil, s.err
 
520
        }
 
521
 
 
522
        for {
 
523
                packet, err := s.transport.readPacket()
 
524
                if err != nil {
 
525
 
 
526
                        s.lock.Lock()
 
527
                        s.err = err
 
528
                        s.lock.Unlock()
 
529
 
 
530
                        // TODO(dfc) s.lock protects s.channels but isn't being held here.
 
531
                        for _, c := range s.channels {
 
532
                                c.setDead()
 
533
                                c.handleData(nil)
 
534
                        }
 
535
 
 
536
                        return nil, err
 
537
                }
 
538
 
 
539
                switch packet[0] {
 
540
                case msgChannelData:
 
541
                        if len(packet) < 9 {
 
542
                                // malformed data packet
 
543
                                return nil, ParseError{msgChannelData}
 
544
                        }
 
545
                        remoteId := binary.BigEndian.Uint32(packet[1:5])
 
546
                        s.lock.Lock()
 
547
                        c, ok := s.channels[remoteId]
 
548
                        if !ok {
 
549
                                s.lock.Unlock()
 
550
                                continue
 
551
                        }
 
552
                        if length := binary.BigEndian.Uint32(packet[5:9]); length > 0 {
 
553
                                packet = packet[9:]
 
554
                                c.handleData(packet[:length])
 
555
                        }
 
556
                        s.lock.Unlock()
 
557
                default:
 
558
                        decoded, err := decode(packet)
 
559
                        if err != nil {
 
560
                                return nil, err
 
561
                        }
 
562
                        switch msg := decoded.(type) {
 
563
                        case *channelOpenMsg:
 
564
                                if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
 
565
                                        return nil, errors.New("ssh: invalid MaxPacketSize from peer")
 
566
                                }
 
567
                                c := &serverChan{
 
568
                                        channel: channel{
 
569
                                                packetConn: s.transport,
 
570
                                                remoteId:   msg.PeersId,
 
571
                                                remoteWin:  window{Cond: newCond()},
 
572
                                                maxPacket:  msg.MaxPacketSize,
 
573
                                        },
 
574
                                        chanType:    msg.ChanType,
 
575
                                        extraData:   msg.TypeSpecificData,
 
576
                                        myWindow:    defaultWindowSize,
 
577
                                        serverConn:  s,
 
578
                                        cond:        newCond(),
 
579
                                        pendingData: make([]byte, defaultWindowSize),
 
580
                                }
 
581
                                c.remoteWin.add(msg.PeersWindow)
 
582
                                s.lock.Lock()
 
583
                                c.localId = s.nextChanId
 
584
                                s.nextChanId++
 
585
                                s.channels[c.localId] = c
 
586
                                s.lock.Unlock()
 
587
                                return c, nil
 
588
 
 
589
                        case *channelRequestMsg:
 
590
                                s.lock.Lock()
 
591
                                c, ok := s.channels[msg.PeersId]
 
592
                                if !ok {
 
593
                                        s.lock.Unlock()
 
594
                                        continue
 
595
                                }
 
596
                                c.handlePacket(msg)
 
597
                                s.lock.Unlock()
 
598
 
 
599
                        case *windowAdjustMsg:
 
600
                                s.lock.Lock()
 
601
                                c, ok := s.channels[msg.PeersId]
 
602
                                if !ok {
 
603
                                        s.lock.Unlock()
 
604
                                        continue
 
605
                                }
 
606
                                c.handlePacket(msg)
 
607
                                s.lock.Unlock()
 
608
 
 
609
                        case *channelEOFMsg:
 
610
                                s.lock.Lock()
 
611
                                c, ok := s.channels[msg.PeersId]
 
612
                                if !ok {
 
613
                                        s.lock.Unlock()
 
614
                                        continue
 
615
                                }
 
616
                                c.handlePacket(msg)
 
617
                                s.lock.Unlock()
 
618
 
 
619
                        case *channelCloseMsg:
 
620
                                s.lock.Lock()
 
621
                                c, ok := s.channels[msg.PeersId]
 
622
                                if !ok {
 
623
                                        s.lock.Unlock()
 
624
                                        continue
 
625
                                }
 
626
                                c.handlePacket(msg)
 
627
                                s.lock.Unlock()
 
628
 
 
629
                        case *globalRequestMsg:
 
630
                                if msg.WantReply {
 
631
                                        if err := s.transport.writePacket([]byte{msgRequestFailure}); err != nil {
 
632
                                                return nil, err
 
633
                                        }
 
634
                                }
 
635
 
 
636
                        case *kexInitMsg:
 
637
                                s.lock.Lock()
 
638
                                if err := s.clientInitHandshake(msg, packet); err != nil {
 
639
                                        s.lock.Unlock()
 
640
                                        return nil, err
 
641
                                }
 
642
                                s.lock.Unlock()
 
643
                        case *disconnectMsg:
 
644
                                return nil, io.EOF
 
645
                        default:
 
646
                                // Unknown message. Ignore.
 
647
                        }
 
648
                }
 
649
        }
 
650
 
 
651
        panic("unreachable")
 
652
}
 
653
 
 
654
// A Listener implements a network listener (net.Listener) for SSH connections.
 
655
type Listener struct {
 
656
        listener net.Listener
 
657
        config   *ServerConfig
 
658
}
 
659
 
 
660
// Addr returns the listener's network address.
 
661
func (l *Listener) Addr() net.Addr {
 
662
        return l.listener.Addr()
 
663
}
 
664
 
 
665
// Close closes the listener.
 
666
func (l *Listener) Close() error {
 
667
        return l.listener.Close()
 
668
}
 
669
 
 
670
// Accept waits for and returns the next incoming SSH connection.
 
671
// The receiver should call Handshake() in another goroutine
 
672
// to avoid blocking the accepter.
 
673
func (l *Listener) Accept() (*ServerConn, error) {
 
674
        c, err := l.listener.Accept()
 
675
        if err != nil {
 
676
                return nil, err
 
677
        }
 
678
        return Server(c, l.config), nil
 
679
}
 
680
 
 
681
// Listen creates an SSH listener accepting connections on
 
682
// the given network address using net.Listen.
 
683
func Listen(network, addr string, config *ServerConfig) (*Listener, error) {
 
684
        l, err := net.Listen(network, addr)
 
685
        if err != nil {
 
686
                return nil, err
 
687
        }
 
688
        return &Listener{
 
689
                l,
 
690
                config,
 
691
        }, nil
 
692
}