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/base64" 6 "errors" 7 "fmt" 8 "net" 9 "sync" 10 "time" 11 12 gossh "golang.org/x/crypto/ssh" 13) 14 15// ErrServerClosed is returned by the Server's Serve, ListenAndServe, 16// and ListenAndServeTLS methods after a call to Shutdown or Close. 17var ErrServerClosed = errors.New("ssh: Server closed") 18 19type SubsystemHandler func(s Session) 20 21var DefaultSubsystemHandlers = map[string]SubsystemHandler{} 22 23type RequestHandler func(ctx Context, srv *Server, req *gossh.Request) (ok bool, payload []byte) 24 25var DefaultRequestHandlers = map[string]RequestHandler{} 26 27type ChannelHandler func(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChannel, ctx Context) 28 29var DefaultChannelHandlers = map[string]ChannelHandler{ 30 "session": DefaultSessionHandler, 31} 32 33var permissionsPublicKeyExt = "gliderlabs/ssh.PublicKey" 34 35func ensureNoPKInPermissions(ctx Context) error { 36 if _, ok := ctx.Permissions().Permissions.Extensions[permissionsPublicKeyExt]; ok { 37 return errors.New("misconfigured server: public key incorrectly set") 38 } 39 40 return nil 41} 42 43// Server defines parameters for running an SSH server. The zero value for 44// Server is a valid configuration. When both PasswordHandler and 45// PublicKeyHandler are nil, no client authentication is performed. 46type Server struct { 47 Addr string // TCP address to listen on, ":22" if empty 48 Handler Handler // handler to invoke, ssh.DefaultHandler if nil 49 HostSigners []Signer // private keys for the host key, must have at least one 50 Version string // server version to be sent before the initial handshake 51 Banner string // server banner 52 53 BannerHandler BannerHandler // server banner handler, overrides Banner 54 KeyboardInteractiveHandler KeyboardInteractiveHandler // keyboard-interactive authentication handler 55 PasswordHandler PasswordHandler // password authentication handler 56 PublicKeyHandler PublicKeyHandler // public key authentication handler 57 PtyCallback PtyCallback // callback for allocating and allowing PTY sessions, ssh.EmulatePtyCallback if nil 58 PtyHandler PtyHandler // pty allocation handler, ssh.emulatePtyHandler if nil 59 ConnCallback ConnCallback // optional callback for wrapping net.Conn before handling 60 LocalPortForwardingCallback LocalPortForwardingCallback // callback for allowing local port forwarding, denies all if nil 61 ReversePortForwardingCallback ReversePortForwardingCallback // callback for allowing reverse port forwarding, denies all if nil 62 ServerConfigCallback ServerConfigCallback // callback for configuring detailed SSH options 63 SessionRequestCallback SessionRequestCallback // callback for allowing or denying SSH sessions 64 65 ConnectionFailedCallback ConnectionFailedCallback // callback to report connection failures 66 67 IdleTimeout time.Duration // connection timeout when no activity, none if empty 68 MaxTimeout time.Duration // absolute connection timeout, none if empty 69 70 // ChannelHandlers allow overriding the built-in session handlers or provide 71 // extensions to the protocol, such as tcpip forwarding. By default only the 72 // "session" handler is enabled. 73 ChannelHandlers map[string]ChannelHandler 74 75 // RequestHandlers allow overriding the server-level request handlers or 76 // provide extensions to the protocol, such as tcpip forwarding. By default 77 // no handlers are enabled. 78 RequestHandlers map[string]RequestHandler 79 80 // SubsystemHandlers are handlers which are similar to the usual SSH command 81 // handlers, but handle named subsystems. 82 SubsystemHandlers map[string]SubsystemHandler 83 84 listenerWg sync.WaitGroup 85 mu sync.RWMutex 86 listeners map[net.Listener]struct{} 87 conns map[*gossh.ServerConn]struct{} 88 connWg sync.WaitGroup 89 doneChan chan struct{} 90} 91 92func (srv *Server) ensureHostSigner() error { 93 srv.mu.Lock() 94 defer srv.mu.Unlock() 95 96 if len(srv.HostSigners) == 0 { 97 signer, err := generateSigner() 98 if err != nil { 99 return err 100 } 101 srv.HostSigners = append(srv.HostSigners, signer) 102 } 103 return nil 104} 105 106func (srv *Server) ensureHandlers() { 107 srv.mu.Lock() 108 defer srv.mu.Unlock() 109 110 if srv.RequestHandlers == nil { 111 srv.RequestHandlers = map[string]RequestHandler{} 112 for k, v := range DefaultRequestHandlers { 113 srv.RequestHandlers[k] = v 114 } 115 } 116 if srv.ChannelHandlers == nil { 117 srv.ChannelHandlers = map[string]ChannelHandler{} 118 for k, v := range DefaultChannelHandlers { 119 srv.ChannelHandlers[k] = v 120 } 121 } 122 if srv.SubsystemHandlers == nil { 123 srv.SubsystemHandlers = map[string]SubsystemHandler{} 124 for k, v := range DefaultSubsystemHandlers { 125 srv.SubsystemHandlers[k] = v 126 } 127 } 128} 129 130func (srv *Server) config(ctx Context) *gossh.ServerConfig { 131 srv.mu.Lock() 132 defer srv.mu.Unlock() 133 134 var config *gossh.ServerConfig 135 if srv.ServerConfigCallback == nil { 136 config = &gossh.ServerConfig{} 137 } else { 138 config = srv.ServerConfigCallback(ctx) 139 } 140 for _, signer := range srv.HostSigners { 141 config.AddHostKey(signer) 142 } 143 if srv.PasswordHandler == nil && srv.PublicKeyHandler == nil && srv.KeyboardInteractiveHandler == nil { 144 config.NoClientAuth = true 145 } 146 if srv.PtyHandler == nil { 147 srv.PtyHandler = emulatePtyHandler 148 } 149 if srv.Version != "" { 150 config.ServerVersion = "SSH-2.0-" + srv.Version 151 } 152 if srv.Banner != "" { 153 config.BannerCallback = func(_ gossh.ConnMetadata) string { 154 return srv.Banner 155 } 156 } 157 if srv.BannerHandler != nil { 158 config.BannerCallback = func(conn gossh.ConnMetadata) string { 159 applyConnMetadata(ctx, conn) 160 return srv.BannerHandler(ctx) 161 } 162 } 163 if srv.PasswordHandler != nil { 164 config.PasswordCallback = func(conn gossh.ConnMetadata, password []byte) (*gossh.Permissions, error) { 165 resetPermissions(ctx) 166 applyConnMetadata(ctx, conn) 167 err := ensureNoPKInPermissions(ctx) 168 if err != nil { 169 return ctx.Permissions().Permissions, err 170 } 171 ok := srv.PasswordHandler(ctx, string(password)) 172 if !ok { 173 return ctx.Permissions().Permissions, fmt.Errorf("permission denied") 174 } 175 return ctx.Permissions().Permissions, nil 176 } 177 } 178 if srv.PublicKeyHandler != nil { 179 config.PublicKeyCallback = func(conn gossh.ConnMetadata, key gossh.PublicKey) (*gossh.Permissions, error) { 180 resetPermissions(ctx) 181 applyConnMetadata(ctx, conn) 182 err := ensureNoPKInPermissions(ctx) 183 if err != nil { 184 return ctx.Permissions().Permissions, err 185 } 186 ok := srv.PublicKeyHandler(ctx, key) 187 if !ok { 188 return ctx.Permissions().Permissions, fmt.Errorf("permission denied") 189 } 190 191 pkStr := base64.StdEncoding.EncodeToString(key.Marshal()) 192 if ctx.Permissions().Permissions.Extensions == nil { 193 ctx.Permissions().Permissions.Extensions = map[string]string{} 194 } 195 ctx.Permissions().Permissions.Extensions[permissionsPublicKeyExt] = pkStr 196 197 return ctx.Permissions().Permissions, nil 198 } 199 } 200 if srv.KeyboardInteractiveHandler != nil { 201 config.KeyboardInteractiveCallback = func(conn gossh.ConnMetadata, challenger gossh.KeyboardInteractiveChallenge) (*gossh.Permissions, error) { 202 resetPermissions(ctx) 203 applyConnMetadata(ctx, conn) 204 ok := srv.KeyboardInteractiveHandler(ctx, challenger) 205 err := ensureNoPKInPermissions(ctx) 206 if err != nil { 207 return ctx.Permissions().Permissions, err 208 } 209 if !ok { 210 return ctx.Permissions().Permissions, fmt.Errorf("permission denied") 211 } 212 return ctx.Permissions().Permissions, nil 213 } 214 } 215 return config 216} 217 218// Handle sets the Handler for the server. 219func (srv *Server) Handle(fn Handler) { 220 srv.mu.Lock() 221 defer srv.mu.Unlock() 222 223 srv.Handler = fn 224} 225 226// Close immediately closes all active listeners and all active 227// connections. 228// 229// Close returns any error returned from closing the Server's 230// underlying Listener(s). 231func (srv *Server) Close() error { 232 srv.mu.Lock() 233 defer srv.mu.Unlock() 234 235 srv.closeDoneChanLocked() 236 err := srv.closeListenersLocked() 237 for c := range srv.conns { 238 c.Close() 239 delete(srv.conns, c) 240 } 241 return err 242} 243 244// Shutdown gracefully shuts down the server without interrupting any 245// active connections. Shutdown works by first closing all open 246// listeners, and then waiting indefinitely for connections to close. 247// If the provided context expires before the shutdown is complete, 248// then the context's error is returned. 249func (srv *Server) Shutdown(ctx context.Context) error { 250 srv.mu.Lock() 251 lnerr := srv.closeListenersLocked() 252 srv.closeDoneChanLocked() 253 srv.mu.Unlock() 254 255 finished := make(chan struct{}, 1) 256 go func() { 257 srv.listenerWg.Wait() 258 srv.connWg.Wait() 259 finished <- struct{}{} 260 }() 261 262 select { 263 case <-ctx.Done(): 264 return ctx.Err() 265 case <-finished: 266 return lnerr 267 } 268} 269 270// Serve accepts incoming connections on the Listener l, creating a new 271// connection goroutine for each. The connection goroutines read requests and then 272// calls srv.Handler to handle sessions. 273// 274// Serve always returns a non-nil error. 275func (srv *Server) Serve(l net.Listener) error { 276 srv.ensureHandlers() 277 defer l.Close() 278 if err := srv.ensureHostSigner(); err != nil { 279 return err 280 } 281 if srv.Handler == nil { 282 srv.Handler = DefaultHandler 283 } 284 var tempDelay time.Duration 285 286 srv.trackListener(l, true) 287 defer srv.trackListener(l, false) 288 for { 289 conn, e := l.Accept() 290 if e != nil { 291 select { 292 case <-srv.getDoneChan(): 293 return ErrServerClosed 294 default: 295 } 296 if ne, ok := e.(net.Error); ok && ne.Temporary() { 297 if tempDelay == 0 { 298 tempDelay = 5 * time.Millisecond 299 } else { 300 tempDelay *= 2 301 } 302 if max := 1 * time.Second; tempDelay > max { 303 tempDelay = max 304 } 305 time.Sleep(tempDelay) 306 continue 307 } 308 return e 309 } 310 go srv.HandleConn(conn) 311 } 312} 313 314func (srv *Server) HandleConn(newConn net.Conn) { 315 ctx, cancel := newContext(srv) 316 if srv.ConnCallback != nil { 317 cbConn := srv.ConnCallback(ctx, newConn) 318 if cbConn == nil { 319 newConn.Close() 320 return 321 } 322 newConn = cbConn 323 } 324 conn := &serverConn{ 325 Conn: newConn, 326 idleTimeout: srv.IdleTimeout, 327 closeCanceler: cancel, 328 } 329 if srv.MaxTimeout > 0 { 330 conn.maxDeadline = time.Now().Add(srv.MaxTimeout) 331 } 332 defer conn.Close() 333 sshConn, chans, reqs, err := gossh.NewServerConn(conn, srv.config(ctx)) 334 if err != nil { 335 if srv.ConnectionFailedCallback != nil { 336 srv.ConnectionFailedCallback(conn, err) 337 } 338 return 339 } 340 341 if sshConn.Permissions != nil { 342 // Now that the connection was authed, if the permissionsPublicKeyExt was 343 // attached, we need to re-parse it as a public key. 344 if keyData, ok := sshConn.Permissions.Extensions[permissionsPublicKeyExt]; ok { 345 decodedData, err := base64.StdEncoding.DecodeString(keyData) 346 if err != nil { 347 if srv.ConnectionFailedCallback != nil { 348 srv.ConnectionFailedCallback(conn, err) 349 } 350 return 351 } 352 353 key, err := gossh.ParsePublicKey(decodedData) 354 if err != nil { 355 if srv.ConnectionFailedCallback != nil { 356 srv.ConnectionFailedCallback(conn, err) 357 } 358 return 359 } 360 361 ctx.SetValue(ContextKeyPublicKey, key) 362 } 363 } 364 365 // Additionally, now that the connection was authed, we can take the 366 // permissions off of the gossh.Conn and re-attach them to the Permissions 367 // object stored in the Context. 368 ctx.Permissions().Permissions = sshConn.Permissions 369 370 srv.trackConn(sshConn, true) 371 defer srv.trackConn(sshConn, false) 372 373 ctx.SetValue(ContextKeyConn, sshConn) 374 applyConnMetadata(ctx, sshConn) 375 // go gossh.DiscardRequests(reqs) 376 go srv.handleRequests(ctx, reqs) 377 for ch := range chans { 378 handler := srv.ChannelHandlers[ch.ChannelType()] 379 if handler == nil { 380 handler = srv.ChannelHandlers["default"] 381 } 382 if handler == nil { 383 ch.Reject(gossh.UnknownChannelType, "unsupported channel type") 384 continue 385 } 386 go handler(srv, sshConn, ch, ctx) 387 } 388} 389 390func (srv *Server) handleRequests(ctx Context, in <-chan *gossh.Request) { 391 for req := range in { 392 handler := srv.RequestHandlers[req.Type] 393 if handler == nil { 394 handler = srv.RequestHandlers["default"] 395 } 396 if handler == nil { 397 req.Reply(false, nil) 398 continue 399 } 400 /*reqCtx, cancel := context.WithCancel(ctx) 401 defer cancel() */ 402 ret, payload := handler(ctx, srv, req) 403 req.Reply(ret, payload) 404 } 405} 406 407// ListenAndServe listens on the TCP network address srv.Addr and then calls 408// Serve to handle incoming connections. If srv.Addr is blank, ":22" is used. 409// ListenAndServe always returns a non-nil error. 410func (srv *Server) ListenAndServe() error { 411 addr := srv.Addr 412 if addr == "" { 413 addr = ":22" 414 } 415 ln, err := net.Listen("tcp", addr) 416 if err != nil { 417 return err 418 } 419 return srv.Serve(ln) 420} 421 422// AddHostKey adds a private key as a host key. If an existing host key exists 423// with the same algorithm, it is overwritten. Each server config must have at 424// least one host key. 425func (srv *Server) AddHostKey(key Signer) { 426 srv.mu.Lock() 427 defer srv.mu.Unlock() 428 429 // these are later added via AddHostKey on ServerConfig, which performs the 430 // check for one of every algorithm. 431 432 // This check is based on the AddHostKey method from the x/crypto/ssh 433 // library. This allows us to only keep one active key for each type on a 434 // server at once. So, if you're dynamically updating keys at runtime, this 435 // list will not keep growing. 436 for i, k := range srv.HostSigners { 437 if k.PublicKey().Type() == key.PublicKey().Type() { 438 srv.HostSigners[i] = key 439 return 440 } 441 } 442 443 srv.HostSigners = append(srv.HostSigners, key) 444} 445 446// SetOption runs a functional option against the server. 447func (srv *Server) SetOption(option Option) error { 448 // NOTE: there is a potential race here for any option that doesn't call an 449 // internal method. We can't actually lock here because if something calls 450 // (as an example) AddHostKey, it will deadlock. 451 452 // srv.mu.Lock() 453 // defer srv.mu.Unlock() 454 455 return option(srv) 456} 457 458func (srv *Server) getDoneChan() <-chan struct{} { 459 srv.mu.Lock() 460 defer srv.mu.Unlock() 461 462 return srv.getDoneChanLocked() 463} 464 465func (srv *Server) getDoneChanLocked() chan struct{} { 466 if srv.doneChan == nil { 467 srv.doneChan = make(chan struct{}) 468 } 469 return srv.doneChan 470} 471 472func (srv *Server) closeDoneChanLocked() { 473 ch := srv.getDoneChanLocked() 474 select { 475 case <-ch: 476 // Already closed. Don't close again. 477 default: 478 // Safe to close here. We're the only closer, guarded 479 // by srv.mu. 480 close(ch) 481 } 482} 483 484func (srv *Server) closeListenersLocked() error { 485 var err error 486 for ln := range srv.listeners { 487 if cerr := ln.Close(); cerr != nil && err == nil { 488 err = cerr 489 } 490 delete(srv.listeners, ln) 491 } 492 return err 493} 494 495func (srv *Server) trackListener(ln net.Listener, add bool) { 496 srv.mu.Lock() 497 defer srv.mu.Unlock() 498 499 if srv.listeners == nil { 500 srv.listeners = make(map[net.Listener]struct{}) 501 } 502 if add { 503 // If the *Server is being reused after a previous 504 // Close or Shutdown, reset its doneChan: 505 if len(srv.listeners) == 0 && len(srv.conns) == 0 { 506 srv.doneChan = nil 507 } 508 srv.listeners[ln] = struct{}{} 509 srv.listenerWg.Add(1) 510 } else { 511 delete(srv.listeners, ln) 512 srv.listenerWg.Done() 513 } 514} 515 516func (srv *Server) trackConn(c *gossh.ServerConn, add bool) { 517 srv.mu.Lock() 518 defer srv.mu.Unlock() 519 520 if srv.conns == nil { 521 srv.conns = make(map[*gossh.ServerConn]struct{}) 522 } 523 if add { 524 srv.conns[c] = struct{}{} 525 srv.connWg.Add(1) 526 } else { 527 delete(srv.conns, c) 528 srv.connWg.Done() 529 } 530}