From 27642ab3513066b629ce0eaef4d6d77c884730ec Mon Sep 17 00:00:00 2001 From: Ben Ransford Date: Mon, 21 Oct 2019 12:41:46 -0700 Subject: [PATCH] Make Context implement "x/crypto/ssh".ConnMetadata interface It's useful for this package's sshContext to implement ConnMetadata when you want to authenticate user certificates from a PublicKeyHandler. Somewhat realistic example of user certificate checking after this patch: checker := gossh.CertChecker{ IsUserAuthority: func(pub gossh.PublicKey) bool { // our own logic to check whether pub is acceptable return true } } func isUserCertOk(ctx ssh.Context, key ssh.PublicKey) bool { if cert, ok := key.(*gossh.Certificate); ok { _, err := checker.Authenticate(ctx, cert) } } sshServer := &ssh.Server{ // ... PublicKeyHandler: isUserCertOK, } --- context.go | 25 ++++++++++++------------- context_test.go | 13 ++++++++++++- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/context.go b/context.go index 2f61a40..8fc5660 100644 --- a/context.go +++ b/context.go @@ -2,7 +2,6 @@ package ssh import ( "context" - "encoding/hex" "net" "sync" @@ -70,13 +69,13 @@ type Context interface { User() string // SessionID returns the session hash. - SessionID() string + SessionID() []byte // ClientVersion returns the version reported by the client. - ClientVersion() string + ClientVersion() []byte // ServerVersion returns the version reported by the server. - ServerVersion() string + ServerVersion() []byte // RemoteAddr returns the remote address for this connection. RemoteAddr() net.Addr @@ -111,9 +110,9 @@ func applyConnMetadata(ctx Context, conn gossh.ConnMetadata) { if ctx.Value(ContextKeySessionID) != nil { return } - ctx.SetValue(ContextKeySessionID, hex.EncodeToString(conn.SessionID())) - ctx.SetValue(ContextKeyClientVersion, string(conn.ClientVersion())) - ctx.SetValue(ContextKeyServerVersion, string(conn.ServerVersion())) + ctx.SetValue(ContextKeySessionID, conn.SessionID()) + ctx.SetValue(ContextKeyClientVersion, conn.ClientVersion()) + ctx.SetValue(ContextKeyServerVersion, conn.ServerVersion()) ctx.SetValue(ContextKeyUser, conn.User()) ctx.SetValue(ContextKeyLocalAddr, conn.LocalAddr()) ctx.SetValue(ContextKeyRemoteAddr, conn.RemoteAddr()) @@ -127,16 +126,16 @@ func (ctx *sshContext) User() string { return ctx.Value(ContextKeyUser).(string) } -func (ctx *sshContext) SessionID() string { - return ctx.Value(ContextKeySessionID).(string) +func (ctx *sshContext) SessionID() []byte { + return ctx.Value(ContextKeySessionID).([]byte) } -func (ctx *sshContext) ClientVersion() string { - return ctx.Value(ContextKeyClientVersion).(string) +func (ctx *sshContext) ClientVersion() []byte { + return ctx.Value(ContextKeyClientVersion).([]byte) } -func (ctx *sshContext) ServerVersion() string { - return ctx.Value(ContextKeyServerVersion).(string) +func (ctx *sshContext) ServerVersion() []byte { + return ctx.Value(ContextKeyServerVersion).([]byte) } func (ctx *sshContext) RemoteAddr() net.Addr { diff --git a/context_test.go b/context_test.go index f5a9315..254f3d0 100644 --- a/context_test.go +++ b/context_test.go @@ -1,6 +1,10 @@ package ssh -import "testing" +import ( + "testing" + + gossh "golang.org/x/crypto/ssh" +) func TestSetPermissions(t *testing.T) { t.Parallel() @@ -45,3 +49,10 @@ func TestSetValue(t *testing.T) { t.Fatal(err) } } + +func TestContextAsConnMetadata (t *testing.T) { + var s Context = &sshContext{} + if _, ok := s.(gossh.ConnMetadata); !ok { + t.Error("Context unusable as ConnMetadata") + } +}