Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit eac8ec4

Browse files
committed
Move handshake success processing outside the callbacks
Processing the end of the authentication step and the start of the container inside the auth callbacks was always finicky, with the recent issues of go crypto/ssh[1] with regards to the public key callback it is clear that this is not the intended way for them to be used. After investigation of the aforementioned security issue in our dependency, no security compromise was found, the only side-effect was that a container is created before the end of the authentication step during the public key callback, but that is promptly cleaned up when the authentication failed. No access is given if the proper key is not verified. [1] golang/go#70779 Signed-off-by: Nikos Tsipinakis <[email protected]>
1 parent 68d0093 commit eac8ec4

File tree

1 file changed

+67
-65
lines changed

1 file changed

+67
-65
lines changed

internal/sshserver/serverImpl.go

+67-65
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sshserver
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
67
"fmt"
78
"io"
@@ -408,21 +409,16 @@ func (s *serverImpl) createGSSAPIConfig(
408409
}
409410
handlerNetworkConnection.authenticatedMetadata = authenticated
410411
s.logAuthSuccessful(logger, authenticated, "GSSAPI")
411-
sshConnectionHandler, _, err := handlerNetworkConnection.OnHandshakeSuccess(
412-
authenticated,
413-
)
412+
413+
marshaledMetadata, err := json.Marshal(authenticated)
414414
if err != nil {
415-
err = messageCodes.WrapUser(
416-
err,
417-
messageCodes.ESSHBackendRejected,
418-
"Authentication currently unavailable, please try again later.",
419-
"The backend has rejected the user after successful authentication.",
420-
)
421-
logger.Error(err)
422415
return nil, err
423416
}
424-
handlerNetworkConnection.sshConnectionHandler = sshConnectionHandler
425-
return &ssh.Permissions{}, nil
417+
return &ssh.Permissions{
418+
Extensions: map[string]string{
419+
"containerssh-metadata": string(marshaledMetadata),
420+
},
421+
}, err
426422
},
427423
Server: gssServer,
428424
}
@@ -444,27 +440,19 @@ func (s *serverImpl) createKeyboardInteractiveCallback(
444440
conn ssh.ConnMetadata,
445441
challenge ssh.KeyboardInteractiveChallenge,
446442
) (*ssh.Permissions, error) {
447-
permissions, authenticatedMetadata, err := keyboardInteractiveHandler(conn, challenge)
443+
_, authenticatedMetadata, err := keyboardInteractiveHandler(conn, challenge)
448444
if err != nil {
449-
return permissions, err
445+
return nil, err
450446
}
451-
// HACK: check HACKS.md "OnHandshakeSuccess conformanceTestHandler"
452-
sshConnectionHandler, _, err := handlerNetworkConnection.OnHandshakeSuccess(
453-
authenticatedMetadata,
454-
)
447+
marshaledMetadata, err := json.Marshal(authenticatedMetadata)
455448
if err != nil {
456-
err = messageCodes.WrapUser(
457-
err,
458-
messageCodes.ESSHBackendRejected,
459-
"Authentication currently unavailable, please try again later.",
460-
"The backend has rejected the user after successful authentication.",
461-
)
462-
logger.Error(err)
463-
return permissions, err
449+
return nil, err
464450
}
465-
handlerNetworkConnection.authenticatedMetadata = authenticatedMetadata
466-
handlerNetworkConnection.sshConnectionHandler = sshConnectionHandler
467-
return permissions, err
451+
return &ssh.Permissions{
452+
Extensions: map[string]string{
453+
"containerssh-metadata": string(marshaledMetadata),
454+
},
455+
}, err
468456
}
469457
return keyboardInteractiveCallback
470458
}
@@ -476,27 +464,19 @@ func (s *serverImpl) createPubKeyCallback(
476464
) func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
477465
pubKeyHandler := s.createPubKeyAuthenticator(meta, handlerNetworkConnection, logger)
478466
pubkeyCallback := func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
479-
permissions, authenticatedMetadata, err := pubKeyHandler(conn, key)
467+
_, authenticatedMetadata, err := pubKeyHandler(conn, key)
480468
if err != nil {
481-
return permissions, err
469+
return nil, err
482470
}
483-
// HACK: check HACKS.md "OnHandshakeSuccess conformanceTestHandler"
484-
sshConnectionHandler, _, err := handlerNetworkConnection.OnHandshakeSuccess(
485-
authenticatedMetadata,
486-
)
471+
marshaledMetadata, err := json.Marshal(authenticatedMetadata)
487472
if err != nil {
488-
err = messageCodes.WrapUser(
489-
err,
490-
messageCodes.ESSHBackendRejected,
491-
"Authentication currently unavailable, please try again later.",
492-
"The backend has rejected the user after successful authentication.",
493-
)
494-
logger.Error(err)
495-
return permissions, err
473+
return nil, err
496474
}
497-
handlerNetworkConnection.authenticatedMetadata = authenticatedMetadata
498-
handlerNetworkConnection.sshConnectionHandler = sshConnectionHandler
499-
return permissions, err
475+
return &ssh.Permissions{
476+
Extensions: map[string]string{
477+
"containerssh-metadata": string(marshaledMetadata),
478+
},
479+
}, err
500480
}
501481
return pubkeyCallback
502482
}
@@ -508,27 +488,19 @@ func (s *serverImpl) createPasswordCallback(
508488
) func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
509489
passwordHandler := s.createPasswordAuthenticator(meta, handlerNetworkConnection, logger)
510490
passwordCallback := func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
511-
permissions, authenticatedMetadata, err := passwordHandler(conn, password)
491+
_, authenticatedMetadata, err := passwordHandler(conn, password)
512492
if err != nil {
513-
return permissions, err
493+
return nil, err
514494
}
515-
// HACK: check HACKS.md "OnHandshakeSuccess conformanceTestHandler"
516-
sshConnectionHandler, _, err := handlerNetworkConnection.OnHandshakeSuccess(
517-
authenticatedMetadata,
518-
)
495+
marshaledMetadata, err := json.Marshal(authenticatedMetadata)
519496
if err != nil {
520-
err = messageCodes.WrapUser(
521-
err,
522-
messageCodes.ESSHBackendRejected,
523-
"Authentication currently unavailable, please try again later.",
524-
"The backend has rejected the user after successful authentication.",
525-
)
526-
logger.Error(err)
527-
return permissions, err
497+
return nil, err
528498
}
529-
handlerNetworkConnection.authenticatedMetadata = authenticatedMetadata
530-
handlerNetworkConnection.sshConnectionHandler = sshConnectionHandler
531-
return permissions, err
499+
return &ssh.Permissions{
500+
Extensions: map[string]string{
501+
"containerssh-metadata": string(marshaledMetadata),
502+
},
503+
}, err
532504
}
533505
return passwordCallback
534506
}
@@ -572,17 +544,47 @@ func (s *serverImpl) handleConnection(conn net.Conn) {
572544
conn,
573545
s.createConfiguration(connectionMeta, &wrapper, logger),
574546
)
575-
if err != nil {
547+
abortCleanup := func() {
576548
logger.Info(messageCodes.Wrap(err, messageCodes.ESSHHandshakeFailed, "SSH handshake failed"))
577549
handlerNetworkConnection.OnHandshakeFailed(connectionMeta, err)
578550
s.shutdownHandlers.Unregister(shutdownHandlerID)
579551
logger.Debug(messageCodes.NewMessage(messageCodes.MSSHDisconnected, "Client disconnected"))
580552
handlerNetworkConnection.OnDisconnect()
581553
_ = conn.Close()
582554
s.wg.Done()
555+
}
556+
if err != nil {
557+
abortCleanup()
558+
return
559+
}
560+
var authenticatedMetadata metadata.ConnectionAuthenticatedMetadata
561+
marshaledMetadata, ok := sshConn.Permissions.Extensions["containerssh-metadata"]
562+
if !ok {
563+
abortCleanup()
583564
return
584565
}
585-
authenticatedMetadata := wrapper.authenticatedMetadata
566+
err = json.Unmarshal([]byte(marshaledMetadata), &authenticatedMetadata)
567+
if err != nil {
568+
abortCleanup()
569+
return
570+
}
571+
sshConnectionHandler, _, err := handlerNetworkConnection.OnHandshakeSuccess(
572+
authenticatedMetadata,
573+
)
574+
if err != nil {
575+
err = messageCodes.WrapUser(
576+
err,
577+
messageCodes.ESSHBackendRejected,
578+
"Authentication currently unavailable, please try again later.",
579+
"The backend has rejected the user after successful authentication.",
580+
)
581+
logger.Error(err)
582+
abortCleanup()
583+
return
584+
}
585+
wrapper.authenticatedMetadata = authenticatedMetadata
586+
wrapper.sshConnectionHandler = sshConnectionHandler
587+
586588
logger = logger.WithLabel("username", sshConn.User())
587589
logger.Debug(messageCodes.NewMessage(messageCodes.MSSHHandshakeSuccessful, "SSH handshake successful"))
588590
s.lock.Lock()

0 commit comments

Comments
 (0)