package ssh
import (
"context"
"encoding/hex"
"net"
"sync"
gossh "golang.org/x/crypto/ssh"
)
type contextKey struct {
name string
}
var (
ContextKeyUser = &contextKey {"user" }
ContextKeySessionID = &contextKey {"session-id" }
ContextKeyPermissions = &contextKey {"permissions" }
ContextKeyClientVersion = &contextKey {"client-version" }
ContextKeyServerVersion = &contextKey {"server-version" }
ContextKeyLocalAddr = &contextKey {"local-addr" }
ContextKeyRemoteAddr = &contextKey {"remote-addr" }
ContextKeyServer = &contextKey {"ssh-server" }
ContextKeyConn = &contextKey {"ssh-conn" }
ContextKeyPublicKey = &contextKey {"public-key" }
)
type Context interface {
context .Context
sync .Locker
User () string
SessionID () string
ClientVersion () string
ServerVersion () string
RemoteAddr () net .Addr
LocalAddr () net .Addr
Permissions () *Permissions
SetValue (key, value interface {})
}
type sshContext struct {
context .Context
*sync .Mutex
values map [interface {}]interface {}
valuesMu sync .Mutex
}
func newContext(srv *Server ) (*sshContext , context .CancelFunc ) {
innerCtx , cancel := context .WithCancel (context .Background ())
ctx := &sshContext {Context : innerCtx , Mutex : &sync .Mutex {}, values : make (map [interface {}]interface {})}
ctx .SetValue (ContextKeyServer , srv )
perms := &Permissions {&gossh .Permissions {}}
ctx .SetValue (ContextKeyPermissions , perms )
return ctx , cancel
}
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 (ContextKeyUser , conn .User ())
ctx .SetValue (ContextKeyLocalAddr , conn .LocalAddr ())
ctx .SetValue (ContextKeyRemoteAddr , conn .RemoteAddr ())
}
func (ctx *sshContext ) Value (key interface {}) interface {} {
ctx .valuesMu .Lock ()
defer ctx .valuesMu .Unlock ()
if v , ok := ctx .values [key ]; ok {
return v
}
return ctx .Context .Value (key )
}
func (ctx *sshContext ) SetValue (key , value interface {}) {
ctx .valuesMu .Lock ()
defer ctx .valuesMu .Unlock ()
ctx .values [key ] = value
}
func (ctx *sshContext ) User () string {
return ctx .Value (ContextKeyUser ).(string )
}
func (ctx *sshContext ) SessionID () string {
return ctx .Value (ContextKeySessionID ).(string )
}
func (ctx *sshContext ) ClientVersion () string {
return ctx .Value (ContextKeyClientVersion ).(string )
}
func (ctx *sshContext ) ServerVersion () string {
return ctx .Value (ContextKeyServerVersion ).(string )
}
func (ctx *sshContext ) RemoteAddr () net .Addr {
if addr , ok := ctx .Value (ContextKeyRemoteAddr ).(net .Addr ); ok {
return addr
}
return nil
}
func (ctx *sshContext ) LocalAddr () net .Addr {
return ctx .Value (ContextKeyLocalAddr ).(net .Addr )
}
func (ctx *sshContext ) Permissions () *Permissions {
return ctx .Value (ContextKeyPermissions ).(*Permissions )
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .