diff --git a/go.mod b/go.mod index 7f8aba175b44..15b4c8c43f28 100644 --- a/go.mod +++ b/go.mod @@ -60,7 +60,7 @@ require ( go.opentelemetry.io/otel/sdk v1.45.0 go.opentelemetry.io/otel/trace v1.45.0 go.yaml.in/yaml/v3 v3.0.5 - golang.org/x/crypto v0.55.0 + golang.org/x/crypto v0.56.0 golang.org/x/mod v0.40.0 golang.org/x/sync v0.22.0 golang.org/x/sys v0.47.0 diff --git a/go.sum b/go.sum index 6c3a5b710ff3..674ef2cf1710 100644 --- a/go.sum +++ b/go.sum @@ -634,8 +634,8 @@ go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= go.yaml.in/yaml/v4 v4.0.0-rc.4 h1:UP4+v6fFrBIb1l934bDl//mmnoIZEDK0idg1+AIvX5U= go.yaml.in/yaml/v4 v4.0.0-rc.4/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= -golang.org/x/crypto v0.55.0 h1:+KWHjbgOaAQ66dh/YlkZKHlz9ZUlq61AFirAR9ntP8M= -golang.org/x/crypto v0.55.0/go.mod h1:uq0V9dE/fzQuJtbnL+2EhWOE63vo164FY8xqEnV9xis= +golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= +golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE= golang.org/x/net v0.58.0 h1:ynWG7rqYi4ccpTEuPZ2QGWHktVEM9DMCj9yzDE0Q7To= diff --git a/vendor/golang.org/x/crypto/ssh/certs.go b/vendor/golang.org/x/crypto/ssh/certs.go index fa848f51a5f9..a3b802e4b8bf 100644 --- a/vendor/golang.org/x/crypto/ssh/certs.go +++ b/vendor/golang.org/x/crypto/ssh/certs.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "net" + "slices" "sort" "time" ) @@ -305,8 +306,11 @@ const sourceAddressCriticalOption = "source-address" // minimally, the IsAuthority callback should be set. type CertChecker struct { // SupportedCriticalOptions lists the CriticalOptions that the - // server application layer understands. These are only used - // for user certificates. + // application layer understands. A certificate carrying a critical + // option that is not listed here is rejected. + // CertChecker.Authenticate additionally accepts the source-address + // option, which the server enforces on the Permissions that + // Authenticate returns. SupportedCriticalOptions []string // IsUserAuthority should return true if the key is recognized as an @@ -369,8 +373,9 @@ func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) return c.CheckCert(hostname, cert) } -// Authenticate checks a user certificate. Authenticate can be used as -// a value for ServerConfig.PublicKeyCallback. +// Authenticate checks a user certificate. Authenticate can be used as a value +// for ServerConfig.PublicKeyCallback. The source-address critical option is +// allowed, as it will be enforced by the server. func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error) { cert, ok := pubKey.(*Certificate) if !ok { @@ -389,8 +394,11 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis if !c.IsUserAuthority(cert.SignatureKey) { return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") } - - if err := c.CheckCert(conn.User(), cert); err != nil { + // The source-address critical option is enforced by serverAuthenticate, + // so it is supported regardless of SupportedCriticalOptions + cc := *c + cc.SupportedCriticalOptions = append(slices.Clip(cc.SupportedCriticalOptions), sourceAddressCriticalOption) + if err := cc.CheckCert(conn.User(), cert); err != nil { return nil, err } @@ -398,27 +406,15 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis } // CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and -// the signature of the certificate. +// the signature of the certificate. Critical options that are not listed in +// SupportedCriticalOptions are rejected. func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { if c.IsRevoked != nil && c.IsRevoked(cert) { return fmt.Errorf("ssh: certificate serial %d revoked", cert.Serial) } for opt := range cert.CriticalOptions { - // sourceAddressCriticalOption will be enforced by - // serverAuthenticate - if opt == sourceAddressCriticalOption { - continue - } - - found := false - for _, supp := range c.SupportedCriticalOptions { - if supp == opt { - found = true - break - } - } - if !found { + if !slices.Contains(c.SupportedCriticalOptions, opt) { return fmt.Errorf("ssh: unsupported critical option %q in certificate", opt) } } diff --git a/vendor/golang.org/x/crypto/ssh/channel.go b/vendor/golang.org/x/crypto/ssh/channel.go index ba3279e91d68..d6010fd77b99 100644 --- a/vendor/golang.org/x/crypto/ssh/channel.go +++ b/vendor/golang.org/x/crypto/ssh/channel.go @@ -173,6 +173,12 @@ type channel struct { // (for outbound channels) or received (for inbound channels). decided bool + // established is set to true once the channel is open and may carry normal + // channel traffic: for an outbound channel when the peer's open + // confirmation is received, for an inbound channel when the local side + // accepts it. It is set and read from different goroutines. + established atomic.Bool + // direction contains either channelOutbound, for channels created // locally, or channelInbound, for channels created by the peer. direction channelDirection @@ -434,10 +440,20 @@ func (ch *channel) responseMessageReceived() error { return errors.New("ssh: duplicate response received for channel") } ch.decided = true + ch.established.Store(true) return nil } func (ch *channel) handlePacket(packet []byte) error { + // Only the open response is expected before the channel is established. + if !ch.established.Load() { + switch packet[0] { + case msgChannelOpenConfirm, msgChannelOpenFailure: + default: + return nil + } + } + switch packet[0] { case msgChannelData, msgChannelExtendedData: return ch.handleData(packet) @@ -503,7 +519,8 @@ func (ch *channel) handlePacket(packet []byte) error { default: } default: - ch.msg <- msg + // No other message type is expected on an established channel. + return fmt.Errorf("ssh: unexpected message type %d on channel %d", packet[0], ch.localId) } return nil } @@ -554,6 +571,7 @@ func (ch *channel) Accept() (Channel, <-chan *Request, error) { MaxPacketSize: ch.maxIncomingPayload, } ch.decided = true + ch.established.Store(true) if err := ch.sendMessage(confirm); err != nil { return nil, nil, err } diff --git a/vendor/golang.org/x/crypto/ssh/transport.go b/vendor/golang.org/x/crypto/ssh/transport.go index fa3dd6a4299b..540865dfc823 100644 --- a/vendor/golang.org/x/crypto/ssh/transport.go +++ b/vendor/golang.org/x/crypto/ssh/transport.go @@ -331,13 +331,19 @@ func exchangeVersions(rw io.ReadWriter, versionLine []byte) (them []byte, err er // chars const maxVersionStringBytes = 255 +// maxPreVersionLines is the maximum number of lines sent by the peer +// before the version string. Each of these lines is limited to a maximum +// of maxVersionStringBytes chars. Lines sent before the version string +// are silently ignored. +const maxPreVersionLines = 1024 + // Read version string as specified by RFC 4253, section 4.2. func readVersion(r io.Reader) ([]byte, error) { versionString := make([]byte, 0, 64) var ok bool var buf [1]byte - for length := 0; length < maxVersionStringBytes; length++ { + for lines := 0; len(versionString) < maxVersionStringBytes && lines < maxPreVersionLines; { _, err := io.ReadFull(r, buf[:]) if err != nil { return nil, err @@ -347,9 +353,9 @@ func readVersion(r io.Reader) ([]byte, error) { if buf[0] == '\n' { if !bytes.HasPrefix(versionString, []byte("SSH-")) { // RFC 4253 says we need to ignore all version string lines - // except the one containing the SSH version (provided that - // all the lines do not exceed 255 bytes in total). + // except the one containing the SSH version. versionString = versionString[:0] + lines++ continue } ok = true diff --git a/vendor/modules.txt b/vendor/modules.txt index b17bfbeef39b..36eaff2f29d9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1273,8 +1273,8 @@ go.yaml.in/yaml/v3 ## explicit; go 1.18 go.yaml.in/yaml/v4 go.yaml.in/yaml/v4/internal/libyaml -# golang.org/x/crypto v0.55.0 -## explicit; go 1.25.0 +# golang.org/x/crypto v0.56.0 +## explicit; go 1.26.0 golang.org/x/crypto/argon2 golang.org/x/crypto/bcrypt golang.org/x/crypto/blake2b