// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ssh import ( "io" "net" "sync/atomic" "testing" "time" ) func TestClientAuthRestrictedPublicKeyAlgos(t *testing.T) { for _, tt := range []struct { name string key Signer wantError bool }{ {"rsa", testSigners["rsa"], false}, {"dsa", testSigners["dsa"], true}, {"ed25519", testSigners["ed25519"], true}, } { c1, c2, err := netPipe() if err != nil { t.Fatalf("netPipe: %v", err) } defer c1.Close() defer c2.Close() serverConf := &ServerConfig{ PublicKeyAuthAlgorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512}, PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) { return nil, nil }, } serverConf.AddHostKey(testSigners["ecdsap256"]) done := make(chan struct{}) go func() { defer close(done) NewServerConn(c1, serverConf) }() clientConf := ClientConfig{ User: "user", Auth: []AuthMethod{ PublicKeys(tt.key), }, HostKeyCallback: InsecureIgnoreHostKey(), } _, _, _, err = NewClientConn(c2, "", &clientConf) if err != nil { if !tt.wantError { t.Errorf("%s: got unexpected error %q", tt.name, err.Error()) } } else if tt.wantError { t.Errorf("%s: succeeded, but want error", tt.name) } <-done } } func TestNewServerConnValidationErrors(t *testing.T) { serverConf := &ServerConfig{ PublicKeyAuthAlgorithms: []string{CertAlgoRSAv01}, } c := &markerConn{} _, _, _, err := NewServerConn(c, serverConf) if err == nil { t.Fatal("NewServerConn with invalid public key auth algorithms succeeded") } if !c.isClosed() { t.Fatal("NewServerConn with invalid public key auth algorithms left connection open") } if c.isUsed() { t.Fatal("NewServerConn with invalid public key auth algorithms used connection") } serverConf = &ServerConfig{ Config: Config{ KeyExchanges: []string{kexAlgoDHGEXSHA256}, }, } c = &markerConn{} _, _, _, err = NewServerConn(c, serverConf) if err == nil { t.Fatal("NewServerConn with unsupported key exchange succeeded") } if !c.isClosed() { t.Fatal("NewServerConn with unsupported key exchange left connection open") } if c.isUsed() { t.Fatal("NewServerConn with unsupported key exchange used connection") } } type markerConn struct { closed uint32 used uint32 } func (c *markerConn) isClosed() bool { return atomic.LoadUint32(&c.closed) != 0 } func (c *markerConn) isUsed() bool { return atomic.LoadUint32(&c.used) != 0 } func (c *markerConn) Close() error { atomic.StoreUint32(&c.closed, 1) return nil } func (c *markerConn) Read(b []byte) (n int, err error) { atomic.StoreUint32(&c.used, 1) if atomic.LoadUint32(&c.closed) != 0 { return 0, net.ErrClosed } else { return 0, io.EOF } } func (c *markerConn) Write(b []byte) (n int, err error) { atomic.StoreUint32(&c.used, 1) if atomic.LoadUint32(&c.closed) != 0 { return 0, net.ErrClosed } else { return 0, io.ErrClosedPipe } } func (*markerConn) LocalAddr() net.Addr { return nil } func (*markerConn) RemoteAddr() net.Addr { return nil } func (*markerConn) SetDeadline(t time.Time) error { return nil } func (*markerConn) SetReadDeadline(t time.Time) error { return nil } func (*markerConn) SetWriteDeadline(t time.Time) error { return nil }