github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/crypto/ssh/test/cert_test.go (about)

     1  // Copyright 2014 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  //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd
     6  // +build aix darwin dragonfly freebsd linux netbsd openbsd
     7  
     8  package test
     9  
    10  import (
    11  	"bytes"
    12  	"crypto/rand"
    13  	"testing"
    14  
    15  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/crypto/ssh"
    16  )
    17  
    18  // Test both logging in with a cert, and also that the certificate presented by an OpenSSH host can be validated correctly
    19  func TestCertLogin(t *testing.T) {
    20  	s := newServer(t)
    21  	defer s.Shutdown()
    22  
    23  	// Use a key different from the default.
    24  	clientKey := testSigners["dsa"]
    25  	caAuthKey := testSigners["ecdsa"]
    26  	cert := &ssh.Certificate{
    27  		Key:             clientKey.PublicKey(),
    28  		ValidPrincipals: []string{username()},
    29  		CertType:        ssh.UserCert,
    30  		ValidBefore:     ssh.CertTimeInfinity,
    31  	}
    32  	if err := cert.SignCert(rand.Reader, caAuthKey); err != nil {
    33  		t.Fatalf("SetSignature: %v", err)
    34  	}
    35  
    36  	certSigner, err := ssh.NewCertSigner(cert, clientKey)
    37  	if err != nil {
    38  		t.Fatalf("NewCertSigner: %v", err)
    39  	}
    40  
    41  	conf := &ssh.ClientConfig{
    42  		User: username(),
    43  		HostKeyCallback: (&ssh.CertChecker{
    44  			IsHostAuthority: func(pk ssh.PublicKey, addr string) bool {
    45  				return bytes.Equal(pk.Marshal(), testPublicKeys["ca"].Marshal())
    46  			},
    47  		}).CheckHostKey,
    48  	}
    49  	conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
    50  
    51  	for _, test := range []struct {
    52  		addr    string
    53  		succeed bool
    54  	}{
    55  		{addr: "host.example.com:22", succeed: true},
    56  		{addr: "host.example.com:10000", succeed: true}, // non-standard port must be OK
    57  		{addr: "host.example.com", succeed: false},      // port must be specified
    58  		{addr: "host.ex4mple.com:22", succeed: false},   // wrong host
    59  	} {
    60  		client, err := s.TryDialWithAddr(conf, test.addr)
    61  
    62  		// Always close client if opened successfully
    63  		if err == nil {
    64  			client.Close()
    65  		}
    66  
    67  		// Now evaluate whether the test failed or passed
    68  		if test.succeed {
    69  			if err != nil {
    70  				t.Fatalf("TryDialWithAddr: %v", err)
    71  			}
    72  		} else {
    73  			if err == nil {
    74  				t.Fatalf("TryDialWithAddr, unexpected success")
    75  			}
    76  		}
    77  	}
    78  }