x/crypto/ssh: public key authentication example
Fixes golang/go#13902. Adds public key authentication to the password authentication example. Change-Id: I4af0ca627fb15b617cc1ba1c6e0954b013f4d94f Reviewed-on: https://go-review.googlesource.com/29374 Reviewed-by: Han-Wen Nienhuys <hanwen@google.com> Run-TryBot: Han-Wen Nienhuys <hanwen@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
committed by
Han-Wen Nienhuys
parent
484eb34681
commit
bde08f269e
+32
-13
@@ -17,9 +17,29 @@ import (
|
||||
)
|
||||
|
||||
func ExampleNewServerConn() {
|
||||
// Public key authentication is done by comparing
|
||||
// the public key of a received connection
|
||||
// with the entries in the authorized_keys file.
|
||||
authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load authorized_keys, err: %v", err)
|
||||
}
|
||||
|
||||
authorizedKeysMap := map[string]bool{}
|
||||
for len(authorizedKeysBytes) > 0 {
|
||||
pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
authorizedKeysMap[string(pubKey.Marshal())] = true
|
||||
authorizedKeysBytes = rest
|
||||
}
|
||||
|
||||
// An SSH server is represented by a ServerConfig, which holds
|
||||
// certificate details and handles authentication of ServerConns.
|
||||
config := &ssh.ServerConfig{
|
||||
// Remove to disable password auth.
|
||||
PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
|
||||
// Should use constant-time compare (or better, salt+hash) in
|
||||
// a production setting.
|
||||
@@ -28,6 +48,14 @@ func ExampleNewServerConn() {
|
||||
}
|
||||
return nil, fmt.Errorf("password rejected for %q", c.User())
|
||||
},
|
||||
|
||||
// Remove to disable public key auth.
|
||||
PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
|
||||
if authorizedKeysMap[string(pubKey.Marshal())] {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unknown public key for %q", c.User())
|
||||
},
|
||||
}
|
||||
|
||||
privateBytes, err := ioutil.ReadFile("id_rsa")
|
||||
@@ -62,6 +90,8 @@ func ExampleNewServerConn() {
|
||||
// The incoming Request channel must be serviced.
|
||||
go ssh.DiscardRequests(reqs)
|
||||
|
||||
// Service the incoming Channel channel.
|
||||
|
||||
// Service the incoming Channel channel.
|
||||
for newChannel := range chans {
|
||||
// Channels have a type, depending on the application level
|
||||
@@ -74,7 +104,7 @@ func ExampleNewServerConn() {
|
||||
}
|
||||
channel, requests, err := newChannel.Accept()
|
||||
if err != nil {
|
||||
log.Fatal("could not accept channel: ", err)
|
||||
log.Fatalf("Could not accept channel: %v", err)
|
||||
}
|
||||
|
||||
// Sessions have out-of-band requests such as "shell",
|
||||
@@ -82,18 +112,7 @@ func ExampleNewServerConn() {
|
||||
// "shell" request.
|
||||
go func(in <-chan *ssh.Request) {
|
||||
for req := range in {
|
||||
ok := false
|
||||
switch req.Type {
|
||||
case "shell":
|
||||
ok = true
|
||||
if len(req.Payload) > 0 {
|
||||
// We don't accept any
|
||||
// commands, only the
|
||||
// default shell.
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
req.Reply(ok, nil)
|
||||
req.Reply(req.Type == "shell", nil)
|
||||
}
|
||||
}(requests)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user