...

Source file src/golang.org/x/crypto/ssh/test/sshcli_test.go

Documentation: golang.org/x/crypto/ssh/test

     1  // Copyright 2023 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 test
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"runtime"
    14  	"testing"
    15  
    16  	"golang.org/x/crypto/internal/testenv"
    17  	"golang.org/x/crypto/ssh"
    18  	"golang.org/x/crypto/ssh/testdata"
    19  )
    20  
    21  func sshClient(t *testing.T) string {
    22  	if testing.Short() {
    23  		t.Skip("Skipping test that executes OpenSSH in -short mode")
    24  	}
    25  	sshCLI := os.Getenv("SSH_CLI_PATH")
    26  	if sshCLI == "" {
    27  		sshCLI = "ssh"
    28  	}
    29  	var err error
    30  	sshCLI, err = exec.LookPath(sshCLI)
    31  	if err != nil {
    32  		t.Skipf("Can't find an ssh(1) client to test against: %v", err)
    33  	}
    34  	return sshCLI
    35  }
    36  
    37  func TestSSHCLIAuth(t *testing.T) {
    38  	if runtime.GOOS == "windows" {
    39  		t.Skipf("always fails on Windows, see #64403")
    40  	}
    41  	sshCLI := sshClient(t)
    42  	dir := t.TempDir()
    43  	keyPrivPath := filepath.Join(dir, "rsa")
    44  
    45  	for fn, content := range map[string][]byte{
    46  		keyPrivPath:                        testdata.PEMBytes["rsa"],
    47  		keyPrivPath + ".pub":               ssh.MarshalAuthorizedKey(testPublicKeys["rsa"]),
    48  		filepath.Join(dir, "rsa-cert.pub"): testdata.SSHCertificates["rsa-user-testcertificate"],
    49  	} {
    50  		if err := os.WriteFile(fn, content, 0600); err != nil {
    51  			t.Fatalf("WriteFile(%q): %v", fn, err)
    52  		}
    53  	}
    54  
    55  	certChecker := ssh.CertChecker{
    56  		IsUserAuthority: func(k ssh.PublicKey) bool {
    57  			return bytes.Equal(k.Marshal(), testPublicKeys["ca"].Marshal())
    58  		},
    59  		UserKeyFallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
    60  			if conn.User() == "testpubkey" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
    61  				return nil, nil
    62  			}
    63  
    64  			return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
    65  		},
    66  	}
    67  
    68  	config := &ssh.ServerConfig{
    69  		PublicKeyCallback: certChecker.Authenticate,
    70  	}
    71  	config.AddHostKey(testSigners["rsa"])
    72  
    73  	server, err := newTestServer(config)
    74  	if err != nil {
    75  		t.Fatalf("unable to start test server: %v", err)
    76  	}
    77  	defer server.Close()
    78  
    79  	port, err := server.port()
    80  	if err != nil {
    81  		t.Fatalf("unable to get server port: %v", err)
    82  	}
    83  
    84  	// test public key authentication.
    85  	cmd := testenv.Command(t, sshCLI, "-vvv", "-i", keyPrivPath, "-o", "StrictHostKeyChecking=no",
    86  		"-p", port, "testpubkey@127.0.0.1", "true")
    87  	out, err := cmd.CombinedOutput()
    88  	if err != nil {
    89  		t.Fatalf("public key authentication failed, error: %v, command output %q", err, string(out))
    90  	}
    91  	// Test SSH user certificate authentication.
    92  	// The username must match one of the principals included in the certificate.
    93  	// The certificate "rsa-user-testcertificate" has "testcertificate" as principal.
    94  	cmd = testenv.Command(t, sshCLI, "-vvv", "-i", keyPrivPath, "-o", "StrictHostKeyChecking=no",
    95  		"-p", port, "testcertificate@127.0.0.1", "true")
    96  	out, err = cmd.CombinedOutput()
    97  	if err != nil {
    98  		t.Fatalf("user certificate authentication failed, error: %v, command output %q", err, string(out))
    99  	}
   100  }
   101  

View as plain text