a geicko-2 based round robin ranking system designed to test c++ battleship submissions
battleship.dunkirk.sh
1package ssh
2
3import (
4 "context"
5 "encoding/hex"
6 "net"
7 "sync"
8
9 gossh "golang.org/x/crypto/ssh"
10)
11
12// contextKey is a value for use with context.WithValue. It's used as
13// a pointer so it fits in an interface{} without allocation.
14type contextKey struct {
15 name string
16}
17
18var (
19 // ContextKeyUser is a context key for use with Contexts in this package.
20 // The associated value will be of type string.
21 ContextKeyUser = &contextKey{"user"}
22
23 // ContextKeySessionID is a context key for use with Contexts in this package.
24 // The associated value will be of type string.
25 ContextKeySessionID = &contextKey{"session-id"}
26
27 // ContextKeyPermissions is a context key for use with Contexts in this package.
28 // The associated value will be of type *Permissions.
29 ContextKeyPermissions = &contextKey{"permissions"}
30
31 // ContextKeyClientVersion is a context key for use with Contexts in this package.
32 // The associated value will be of type string.
33 ContextKeyClientVersion = &contextKey{"client-version"}
34
35 // ContextKeyServerVersion is a context key for use with Contexts in this package.
36 // The associated value will be of type string.
37 ContextKeyServerVersion = &contextKey{"server-version"}
38
39 // ContextKeyLocalAddr is a context key for use with Contexts in this package.
40 // The associated value will be of type net.Addr.
41 ContextKeyLocalAddr = &contextKey{"local-addr"}
42
43 // ContextKeyRemoteAddr is a context key for use with Contexts in this package.
44 // The associated value will be of type net.Addr.
45 ContextKeyRemoteAddr = &contextKey{"remote-addr"}
46
47 // ContextKeyServer is a context key for use with Contexts in this package.
48 // The associated value will be of type *Server.
49 ContextKeyServer = &contextKey{"ssh-server"}
50
51 // ContextKeyConn is a context key for use with Contexts in this package.
52 // The associated value will be of type gossh.ServerConn.
53 ContextKeyConn = &contextKey{"ssh-conn"}
54
55 // ContextKeyPublicKey is a context key for use with Contexts in this package.
56 // The associated value will be of type PublicKey.
57 ContextKeyPublicKey = &contextKey{"public-key"}
58
59 // ContextKeySession is a context key for use with Contexts in this package.
60 // The associated value will be of type Session.
61 ContextKeySession = &contextKey{"session"}
62)
63
64// Context is a package specific context interface. It exposes connection
65// metadata and allows new values to be easily written to it. It's used in
66// authentication handlers and callbacks, and its underlying context.Context is
67// exposed on Session in the session Handler. A connection-scoped lock is also
68// embedded in the context to make it easier to limit operations per-connection.
69type Context interface {
70 context.Context
71 sync.Locker
72
73 // User returns the username used when establishing the SSH connection.
74 User() string
75
76 // SessionID returns the session hash.
77 SessionID() string
78
79 // ClientVersion returns the version reported by the client.
80 ClientVersion() string
81
82 // ServerVersion returns the version reported by the server.
83 ServerVersion() string
84
85 // RemoteAddr returns the remote address for this connection.
86 RemoteAddr() net.Addr
87
88 // LocalAddr returns the local address for this connection.
89 LocalAddr() net.Addr
90
91 // Permissions returns the Permissions object used for this connection.
92 Permissions() *Permissions
93
94 // SetValue allows you to easily write new values into the underlying context.
95 SetValue(key, value interface{})
96}
97
98type sshContext struct {
99 context.Context
100 *sync.Mutex
101
102 values map[interface{}]interface{}
103 valuesMu sync.Mutex
104}
105
106var _ context.Context = &sshContext{}
107
108var _ sync.Locker = &sshContext{}
109
110func newContext(srv *Server) (*sshContext, context.CancelFunc) {
111 innerCtx, cancel := context.WithCancel(context.Background())
112 ctx := &sshContext{
113 Context: innerCtx,
114 Mutex: &sync.Mutex{},
115 values: make(map[interface{}]interface{}),
116 }
117 ctx.SetValue(ContextKeyServer, srv)
118 perms := &Permissions{&gossh.Permissions{}}
119 ctx.SetValue(ContextKeyPermissions, perms)
120 return ctx, cancel
121}
122
123func resetPermissions(ctx Context) {
124 ctx.Permissions().Permissions = &gossh.Permissions{}
125}
126
127// this is separate from newContext because we will get ConnMetadata
128// at different points so it needs to be applied separately
129func applyConnMetadata(ctx Context, conn gossh.ConnMetadata) {
130 if ctx.Value(ContextKeySessionID) != nil {
131 return
132 }
133 ctx.SetValue(ContextKeySessionID, hex.EncodeToString(conn.SessionID()))
134 ctx.SetValue(ContextKeyClientVersion, string(conn.ClientVersion()))
135 ctx.SetValue(ContextKeyServerVersion, string(conn.ServerVersion()))
136 ctx.SetValue(ContextKeyUser, conn.User())
137 ctx.SetValue(ContextKeyLocalAddr, conn.LocalAddr())
138 ctx.SetValue(ContextKeyRemoteAddr, conn.RemoteAddr())
139}
140
141func (ctx *sshContext) Value(key interface{}) interface{} {
142 ctx.valuesMu.Lock()
143 defer ctx.valuesMu.Unlock()
144 if v, ok := ctx.values[key]; ok {
145 return v
146 }
147 return ctx.Context.Value(key)
148}
149
150func (ctx *sshContext) SetValue(key, value interface{}) {
151 ctx.valuesMu.Lock()
152 defer ctx.valuesMu.Unlock()
153 ctx.values[key] = value
154}
155
156func (ctx *sshContext) User() string {
157 return ctx.Value(ContextKeyUser).(string)
158}
159
160func (ctx *sshContext) SessionID() string {
161 return ctx.Value(ContextKeySessionID).(string)
162}
163
164func (ctx *sshContext) ClientVersion() string {
165 return ctx.Value(ContextKeyClientVersion).(string)
166}
167
168func (ctx *sshContext) ServerVersion() string {
169 return ctx.Value(ContextKeyServerVersion).(string)
170}
171
172func (ctx *sshContext) RemoteAddr() net.Addr {
173 if addr, ok := ctx.Value(ContextKeyRemoteAddr).(net.Addr); ok {
174 return addr
175 }
176 return nil
177}
178
179func (ctx *sshContext) LocalAddr() net.Addr {
180 return ctx.Value(ContextKeyLocalAddr).(net.Addr)
181}
182
183func (ctx *sshContext) Permissions() *Permissions {
184 return ctx.Value(ContextKeyPermissions).(*Permissions)
185}