Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
405cb3bdea | ||
|
|
913d3ae741 | ||
|
|
dbb6ec16ec | ||
|
|
403f69900e | ||
|
|
055043dfed | ||
|
|
08396bb92b | ||
|
|
9d2ee975ef | ||
|
|
4e5a26183e | ||
|
|
152cdb1503 | ||
|
|
fdfe1f8531 | ||
|
|
b8ffc16e10 | ||
|
|
7e6fbd82c8 | ||
|
|
bda2f3f5cf |
@@ -199,8 +199,8 @@ TEXT ·mixBlocksSSE2(SB), 4, $0-32
|
||||
MOVQ out+0(FP), DX
|
||||
MOVQ a+8(FP), AX
|
||||
MOVQ b+16(FP), BX
|
||||
MOVQ a+24(FP), CX
|
||||
MOVQ $128, BP
|
||||
MOVQ c+24(FP), CX
|
||||
MOVQ $128, DI
|
||||
|
||||
loop:
|
||||
MOVOU 0(AX), X0
|
||||
@@ -213,7 +213,7 @@ loop:
|
||||
ADDQ $16, BX
|
||||
ADDQ $16, CX
|
||||
ADDQ $16, DX
|
||||
SUBQ $2, BP
|
||||
SUBQ $2, DI
|
||||
JA loop
|
||||
RET
|
||||
|
||||
@@ -222,8 +222,8 @@ TEXT ·xorBlocksSSE2(SB), 4, $0-32
|
||||
MOVQ out+0(FP), DX
|
||||
MOVQ a+8(FP), AX
|
||||
MOVQ b+16(FP), BX
|
||||
MOVQ a+24(FP), CX
|
||||
MOVQ $128, BP
|
||||
MOVQ c+24(FP), CX
|
||||
MOVQ $128, DI
|
||||
|
||||
loop:
|
||||
MOVOU 0(AX), X0
|
||||
@@ -238,6 +238,6 @@ loop:
|
||||
ADDQ $16, BX
|
||||
ADDQ $16, CX
|
||||
ADDQ $16, DX
|
||||
SUBQ $2, BP
|
||||
SUBQ $2, DI
|
||||
JA loop
|
||||
RET
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7 && amd64 && gc && !purego
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
package blake2b
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.7 && amd64 && gc && !purego
|
||||
//go:build amd64 && gc && !purego
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.7 && amd64 && gc && !purego
|
||||
|
||||
package blake2b
|
||||
|
||||
import "golang.org/x/sys/cpu"
|
||||
|
||||
func init() {
|
||||
useSSE4 = cpu.X86.HasSSE41
|
||||
}
|
||||
|
||||
//go:noescape
|
||||
func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte)
|
||||
|
||||
func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) {
|
||||
if useSSE4 {
|
||||
hashBlocksSSE4(h, c, flag, blocks)
|
||||
} else {
|
||||
hashBlocksGeneric(h, c, flag, blocks)
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.9
|
||||
|
||||
package blake2b
|
||||
|
||||
import (
|
||||
|
||||
@@ -4,8 +4,8 @@ go 1.18
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.10.0 // tagx:ignore
|
||||
golang.org/x/sys v0.15.0
|
||||
golang.org/x/term v0.15.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/term v0.17.0
|
||||
)
|
||||
|
||||
require golang.org/x/text v0.14.0 // indirect
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.13
|
||||
|
||||
package poly1305
|
||||
|
||||
// Generic fallbacks for the math/bits intrinsics, copied from
|
||||
// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had
|
||||
// variable time fallbacks until Go 1.13.
|
||||
|
||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
|
||||
sum = x + y + carry
|
||||
carryOut = ((x & y) | ((x | y) &^ sum)) >> 63
|
||||
return
|
||||
}
|
||||
|
||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
|
||||
diff = x - y - borrow
|
||||
borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63
|
||||
return
|
||||
}
|
||||
|
||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
|
||||
const mask32 = 1<<32 - 1
|
||||
x0 := x & mask32
|
||||
x1 := x >> 32
|
||||
y0 := y & mask32
|
||||
y1 := y >> 32
|
||||
w0 := x0 * y0
|
||||
t := x1*y0 + w0>>32
|
||||
w1 := t & mask32
|
||||
w2 := t >> 32
|
||||
w1 += x0 * y1
|
||||
hi = x1*y1 + w2 + w1>>32
|
||||
lo = x * y
|
||||
return
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.13
|
||||
|
||||
package poly1305
|
||||
|
||||
import "math/bits"
|
||||
|
||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
|
||||
return bits.Add64(x, y, carry)
|
||||
}
|
||||
|
||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
|
||||
return bits.Sub64(x, y, borrow)
|
||||
}
|
||||
|
||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
|
||||
return bits.Mul64(x, y)
|
||||
}
|
||||
@@ -7,7 +7,10 @@
|
||||
|
||||
package poly1305
|
||||
|
||||
import "encoding/binary"
|
||||
import (
|
||||
"encoding/binary"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag
|
||||
// for a 64 bytes message is approximately
|
||||
@@ -114,13 +117,13 @@ type uint128 struct {
|
||||
}
|
||||
|
||||
func mul64(a, b uint64) uint128 {
|
||||
hi, lo := bitsMul64(a, b)
|
||||
hi, lo := bits.Mul64(a, b)
|
||||
return uint128{lo, hi}
|
||||
}
|
||||
|
||||
func add128(a, b uint128) uint128 {
|
||||
lo, c := bitsAdd64(a.lo, b.lo, 0)
|
||||
hi, c := bitsAdd64(a.hi, b.hi, c)
|
||||
lo, c := bits.Add64(a.lo, b.lo, 0)
|
||||
hi, c := bits.Add64(a.hi, b.hi, c)
|
||||
if c != 0 {
|
||||
panic("poly1305: unexpected overflow")
|
||||
}
|
||||
@@ -155,8 +158,8 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
// hide leading zeroes. For full chunks, that's 1 << 128, so we can just
|
||||
// add 1 to the most significant (2¹²⁸) limb, h2.
|
||||
if len(msg) >= TagSize {
|
||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
||||
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
||||
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
||||
h2 += c + 1
|
||||
|
||||
msg = msg[TagSize:]
|
||||
@@ -165,8 +168,8 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
copy(buf[:], msg)
|
||||
buf[len(msg)] = 1
|
||||
|
||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
||||
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
||||
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
||||
h2 += c
|
||||
|
||||
msg = nil
|
||||
@@ -219,9 +222,9 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
m3 := h2r1
|
||||
|
||||
t0 := m0.lo
|
||||
t1, c := bitsAdd64(m1.lo, m0.hi, 0)
|
||||
t2, c := bitsAdd64(m2.lo, m1.hi, c)
|
||||
t3, _ := bitsAdd64(m3.lo, m2.hi, c)
|
||||
t1, c := bits.Add64(m1.lo, m0.hi, 0)
|
||||
t2, c := bits.Add64(m2.lo, m1.hi, c)
|
||||
t3, _ := bits.Add64(m3.lo, m2.hi, c)
|
||||
|
||||
// Now we have the result as 4 64-bit limbs, and we need to reduce it
|
||||
// modulo 2¹³⁰ - 5. The special shape of this Crandall prime lets us do
|
||||
@@ -243,14 +246,14 @@ func updateGeneric(state *macState, msg []byte) {
|
||||
|
||||
// To add c * 5 to h, we first add cc = c * 4, and then add (cc >> 2) = c.
|
||||
|
||||
h0, c = bitsAdd64(h0, cc.lo, 0)
|
||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
||||
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||
h1, c = bits.Add64(h1, cc.hi, c)
|
||||
h2 += c
|
||||
|
||||
cc = shiftRightBy2(cc)
|
||||
|
||||
h0, c = bitsAdd64(h0, cc.lo, 0)
|
||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
||||
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||
h1, c = bits.Add64(h1, cc.hi, c)
|
||||
h2 += c
|
||||
|
||||
// h2 is at most 3 + 1 + 1 = 5, making the whole of h at most
|
||||
@@ -287,9 +290,9 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
||||
// in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the
|
||||
// result if the subtraction underflows, and t otherwise.
|
||||
|
||||
hMinusP0, b := bitsSub64(h0, p0, 0)
|
||||
hMinusP1, b := bitsSub64(h1, p1, b)
|
||||
_, b = bitsSub64(h2, p2, b)
|
||||
hMinusP0, b := bits.Sub64(h0, p0, 0)
|
||||
hMinusP1, b := bits.Sub64(h1, p1, b)
|
||||
_, b = bits.Sub64(h2, p2, b)
|
||||
|
||||
// h = h if h < p else h - p
|
||||
h0 = select64(b, h0, hMinusP0)
|
||||
@@ -301,8 +304,8 @@ func finalize(out *[TagSize]byte, h *[3]uint64, s *[2]uint64) {
|
||||
//
|
||||
// by just doing a wide addition with the 128 low bits of h and discarding
|
||||
// the overflow.
|
||||
h0, c := bitsAdd64(h0, s[0], 0)
|
||||
h1, _ = bitsAdd64(h1, s[1], c)
|
||||
h0, c := bits.Add64(h0, s[0], 0)
|
||||
h1, _ = bits.Add64(h1, s[1], c)
|
||||
|
||||
binary.LittleEndian.PutUint64(out[0:8], h0)
|
||||
binary.LittleEndian.PutUint64(out[8:16], h1)
|
||||
|
||||
@@ -319,9 +319,9 @@
|
||||
MOVQ rDi, _si(oState); \
|
||||
MOVQ rDo, _so(oState) \
|
||||
|
||||
// func keccakF1600(state *[25]uint64)
|
||||
// func keccakF1600(a *[25]uint64)
|
||||
TEXT ·keccakF1600(SB), 0, $200-8
|
||||
MOVQ state+0(FP), rpState
|
||||
MOVQ a+0(FP), rpState
|
||||
|
||||
// Convert the user state into an internal state
|
||||
NOTQ _be(rpState)
|
||||
|
||||
+20
-8
@@ -187,9 +187,11 @@ type channel struct {
|
||||
pending *buffer
|
||||
extPending *buffer
|
||||
|
||||
// windowMu protects myWindow, the flow-control window.
|
||||
windowMu sync.Mutex
|
||||
myWindow uint32
|
||||
// windowMu protects myWindow, the flow-control window, and myConsumed,
|
||||
// the number of bytes consumed since we last increased myWindow
|
||||
windowMu sync.Mutex
|
||||
myWindow uint32
|
||||
myConsumed uint32
|
||||
|
||||
// writeMu serializes calls to mux.conn.writePacket() and
|
||||
// protects sentClose and packetPool. This mutex must be
|
||||
@@ -332,14 +334,24 @@ func (ch *channel) handleData(packet []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *channel) adjustWindow(n uint32) error {
|
||||
func (c *channel) adjustWindow(adj uint32) error {
|
||||
c.windowMu.Lock()
|
||||
// Since myWindow is managed on our side, and can never exceed
|
||||
// the initial window setting, we don't worry about overflow.
|
||||
c.myWindow += uint32(n)
|
||||
// Since myConsumed and myWindow are managed on our side, and can never
|
||||
// exceed the initial window setting, we don't worry about overflow.
|
||||
c.myConsumed += adj
|
||||
var sendAdj uint32
|
||||
if (channelWindowSize-c.myWindow > 3*c.maxIncomingPayload) ||
|
||||
(c.myWindow < channelWindowSize/2) {
|
||||
sendAdj = c.myConsumed
|
||||
c.myConsumed = 0
|
||||
c.myWindow += sendAdj
|
||||
}
|
||||
c.windowMu.Unlock()
|
||||
if sendAdj == 0 {
|
||||
return nil
|
||||
}
|
||||
return c.sendMessage(windowAdjustMsg{
|
||||
AdditionalBytes: uint32(n),
|
||||
AdditionalBytes: sendAdj,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ func NewClientConn(c net.Conn, addr string, config *ClientConfig) (Conn, <-chan
|
||||
|
||||
if err := conn.clientHandshake(addr, &fullConf); err != nil {
|
||||
c.Close()
|
||||
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", err)
|
||||
return nil, nil, nil, fmt.Errorf("ssh: handshake failed: %w", err)
|
||||
}
|
||||
conn.mux = newMux(conn.transport)
|
||||
return conn, conn.mux.incomingChannels, conn.mux.incomingRequests, nil
|
||||
|
||||
+23
-2
@@ -7,6 +7,9 @@ package ssh
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
@@ -207,9 +210,12 @@ func TestBannerCallback(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewClientConn(t *testing.T) {
|
||||
errHostKeyMismatch := errors.New("host key mismatch")
|
||||
|
||||
for _, tt := range []struct {
|
||||
name string
|
||||
user string
|
||||
name string
|
||||
user string
|
||||
simulateHostKeyMismatch HostKeyCallback
|
||||
}{
|
||||
{
|
||||
name: "good user field for ConnMetadata",
|
||||
@@ -219,6 +225,13 @@ func TestNewClientConn(t *testing.T) {
|
||||
name: "empty user field for ConnMetadata",
|
||||
user: "",
|
||||
},
|
||||
{
|
||||
name: "host key mismatch",
|
||||
user: "testuser",
|
||||
simulateHostKeyMismatch: func(hostname string, remote net.Addr, key PublicKey) error {
|
||||
return fmt.Errorf("%w: %s", errHostKeyMismatch, bytes.TrimSpace(MarshalAuthorizedKey(key)))
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c1, c2, err := netPipe()
|
||||
@@ -243,8 +256,16 @@ func TestNewClientConn(t *testing.T) {
|
||||
},
|
||||
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
if tt.simulateHostKeyMismatch != nil {
|
||||
clientConf.HostKeyCallback = tt.simulateHostKeyMismatch
|
||||
}
|
||||
|
||||
clientConn, _, _, err := NewClientConn(c2, "", clientConf)
|
||||
if err != nil {
|
||||
if tt.simulateHostKeyMismatch != nil && errors.Is(err, errHostKeyMismatch) {
|
||||
return
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
+52
-4
@@ -35,6 +35,16 @@ type keyingTransport interface {
|
||||
// direction will be effected if a msgNewKeys message is sent
|
||||
// or received.
|
||||
prepareKeyChange(*algorithms, *kexResult) error
|
||||
|
||||
// setStrictMode sets the strict KEX mode, notably triggering
|
||||
// sequence number resets on sending or receiving msgNewKeys.
|
||||
// If the sequence number is already > 1 when setStrictMode
|
||||
// is called, an error is returned.
|
||||
setStrictMode() error
|
||||
|
||||
// setInitialKEXDone indicates to the transport that the initial key exchange
|
||||
// was completed
|
||||
setInitialKEXDone()
|
||||
}
|
||||
|
||||
// handshakeTransport implements rekeying on top of a keyingTransport
|
||||
@@ -100,6 +110,10 @@ type handshakeTransport struct {
|
||||
|
||||
// The session ID or nil if first kex did not complete yet.
|
||||
sessionID []byte
|
||||
|
||||
// strictMode indicates if the other side of the handshake indicated
|
||||
// that we should be following the strict KEX protocol restrictions.
|
||||
strictMode bool
|
||||
}
|
||||
|
||||
type pendingKex struct {
|
||||
@@ -209,7 +223,10 @@ func (t *handshakeTransport) readLoop() {
|
||||
close(t.incoming)
|
||||
break
|
||||
}
|
||||
if p[0] == msgIgnore || p[0] == msgDebug {
|
||||
// If this is the first kex, and strict KEX mode is enabled,
|
||||
// we don't ignore any messages, as they may be used to manipulate
|
||||
// the packet sequence numbers.
|
||||
if !(t.sessionID == nil && t.strictMode) && (p[0] == msgIgnore || p[0] == msgDebug) {
|
||||
continue
|
||||
}
|
||||
t.incoming <- p
|
||||
@@ -441,6 +458,11 @@ func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
|
||||
return successPacket, nil
|
||||
}
|
||||
|
||||
const (
|
||||
kexStrictClient = "kex-strict-c-v00@openssh.com"
|
||||
kexStrictServer = "kex-strict-s-v00@openssh.com"
|
||||
)
|
||||
|
||||
// sendKexInit sends a key change message.
|
||||
func (t *handshakeTransport) sendKexInit() error {
|
||||
t.mu.Lock()
|
||||
@@ -454,7 +476,6 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||
}
|
||||
|
||||
msg := &kexInitMsg{
|
||||
KexAlgos: t.config.KeyExchanges,
|
||||
CiphersClientServer: t.config.Ciphers,
|
||||
CiphersServerClient: t.config.Ciphers,
|
||||
MACsClientServer: t.config.MACs,
|
||||
@@ -464,6 +485,13 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||
}
|
||||
io.ReadFull(rand.Reader, msg.Cookie[:])
|
||||
|
||||
// We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm,
|
||||
// and possibly to add the ext-info extension algorithm. Since the slice may be the
|
||||
// user owned KeyExchanges, we create our own slice in order to avoid using user
|
||||
// owned memory by mistake.
|
||||
msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+2) // room for kex-strict and ext-info
|
||||
msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
|
||||
|
||||
isServer := len(t.hostKeys) > 0
|
||||
if isServer {
|
||||
for _, k := range t.hostKeys {
|
||||
@@ -488,17 +516,24 @@ func (t *handshakeTransport) sendKexInit() error {
|
||||
msg.ServerHostKeyAlgos = append(msg.ServerHostKeyAlgos, keyFormat)
|
||||
}
|
||||
}
|
||||
|
||||
if t.sessionID == nil {
|
||||
msg.KexAlgos = append(msg.KexAlgos, kexStrictServer)
|
||||
}
|
||||
} else {
|
||||
msg.ServerHostKeyAlgos = t.hostKeyAlgorithms
|
||||
|
||||
// As a client we opt in to receiving SSH_MSG_EXT_INFO so we know what
|
||||
// algorithms the server supports for public key authentication. See RFC
|
||||
// 8308, Section 2.1.
|
||||
//
|
||||
// We also send the strict KEX mode extension algorithm, in order to opt
|
||||
// into the strict KEX mode.
|
||||
if firstKeyExchange := t.sessionID == nil; firstKeyExchange {
|
||||
msg.KexAlgos = make([]string, 0, len(t.config.KeyExchanges)+1)
|
||||
msg.KexAlgos = append(msg.KexAlgos, t.config.KeyExchanges...)
|
||||
msg.KexAlgos = append(msg.KexAlgos, "ext-info-c")
|
||||
msg.KexAlgos = append(msg.KexAlgos, kexStrictClient)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
packet := Marshal(msg)
|
||||
@@ -604,6 +639,13 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if t.sessionID == nil && ((isClient && contains(serverInit.KexAlgos, kexStrictServer)) || (!isClient && contains(clientInit.KexAlgos, kexStrictClient))) {
|
||||
t.strictMode = true
|
||||
if err := t.conn.setStrictMode(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// We don't send FirstKexFollows, but we handle receiving it.
|
||||
//
|
||||
// RFC 4253 section 7 defines the kex and the agreement method for
|
||||
@@ -679,6 +721,12 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
||||
return unexpectedMessageError(msgNewKeys, packet[0])
|
||||
}
|
||||
|
||||
if firstKeyExchange {
|
||||
// Indicates to the transport that the first key exchange is completed
|
||||
// after receiving SSH_MSG_NEWKEYS.
|
||||
t.conn.setInitialKEXDone()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -395,6 +395,10 @@ func (n *errorKeyingTransport) readPacket() ([]byte, error) {
|
||||
return n.packetConn.readPacket()
|
||||
}
|
||||
|
||||
func (n *errorKeyingTransport) setStrictMode() error { return nil }
|
||||
|
||||
func (n *errorKeyingTransport) setInitialKEXDone() {}
|
||||
|
||||
func TestHandshakeErrorHandlingRead(t *testing.T) {
|
||||
for i := 0; i < 20; i++ {
|
||||
testHandshakeErrorHandlingN(t, i, -1, false)
|
||||
@@ -710,3 +714,308 @@ func TestPickIncompatibleHostKeyAlgo(t *testing.T) {
|
||||
t.Fatal("incompatible signer returned")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrictKEXResetSeqFirstKEX(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" {
|
||||
t.Skip("see golang.org/issue/7237")
|
||||
}
|
||||
|
||||
checker := &syncChecker{
|
||||
waitCall: make(chan int, 10),
|
||||
called: make(chan int, 10),
|
||||
}
|
||||
|
||||
checker.waitCall <- 1
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
<-checker.called
|
||||
|
||||
t.Cleanup(func() {
|
||||
trC.Close()
|
||||
trS.Close()
|
||||
})
|
||||
|
||||
// Throw away the msgExtInfo packet sent during the handshake by the server
|
||||
_, err = trC.readPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
}
|
||||
|
||||
// close the handshake transports before checking the sequence number to
|
||||
// avoid races.
|
||||
trC.Close()
|
||||
trS.Close()
|
||||
|
||||
// check that the sequence number counters. We reset after msgNewKeys, but
|
||||
// then the server immediately writes msgExtInfo, and we close the
|
||||
// transports so we expect read 2, write 0 on the client and read 1, write 1
|
||||
// on the server.
|
||||
if trC.conn.(*transport).reader.seqNum != 2 || trC.conn.(*transport).writer.seqNum != 0 ||
|
||||
trS.conn.(*transport).reader.seqNum != 1 || trS.conn.(*transport).writer.seqNum != 1 {
|
||||
t.Errorf(
|
||||
"unexpected sequence counters:\nclient: reader %d (expected 2), writer %d (expected 0)\nserver: reader %d (expected 1), writer %d (expected 1)",
|
||||
trC.conn.(*transport).reader.seqNum,
|
||||
trC.conn.(*transport).writer.seqNum,
|
||||
trS.conn.(*transport).reader.seqNum,
|
||||
trS.conn.(*transport).writer.seqNum,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrictKEXResetSeqSuccessiveKEX(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" {
|
||||
t.Skip("see golang.org/issue/7237")
|
||||
}
|
||||
|
||||
checker := &syncChecker{
|
||||
waitCall: make(chan int, 10),
|
||||
called: make(chan int, 10),
|
||||
}
|
||||
|
||||
checker.waitCall <- 1
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
<-checker.called
|
||||
|
||||
t.Cleanup(func() {
|
||||
trC.Close()
|
||||
trS.Close()
|
||||
})
|
||||
|
||||
// Throw away the msgExtInfo packet sent during the handshake by the server
|
||||
_, err = trC.readPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
}
|
||||
|
||||
// write and read five packets on either side to bump the sequence numbers
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := trC.writePacket([]byte{msgRequestSuccess}); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
if _, err := trS.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
}
|
||||
if err := trS.writePacket([]byte{msgRequestSuccess}); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
if _, err := trC.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Request a key exchange, which should cause the sequence numbers to reset
|
||||
checker.waitCall <- 1
|
||||
trC.requestKeyExchange()
|
||||
<-checker.called
|
||||
|
||||
// write a packet on the client, and then read it, to verify the key change has actually happened, since
|
||||
// the HostKeyCallback is called _during_ the handshake, so isn't actually indicative of the handshake
|
||||
// finishing.
|
||||
dummyPacket := []byte{99}
|
||||
if err := trS.writePacket(dummyPacket); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
if p, err := trC.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
} else if !bytes.Equal(p, dummyPacket) {
|
||||
t.Fatalf("unexpected packet: got %x, want %x", p, dummyPacket)
|
||||
}
|
||||
|
||||
// close the handshake transports before checking the sequence number to
|
||||
// avoid races.
|
||||
trC.Close()
|
||||
trS.Close()
|
||||
|
||||
if trC.conn.(*transport).reader.seqNum != 2 || trC.conn.(*transport).writer.seqNum != 0 ||
|
||||
trS.conn.(*transport).reader.seqNum != 1 || trS.conn.(*transport).writer.seqNum != 1 {
|
||||
t.Errorf(
|
||||
"unexpected sequence counters:\nclient: reader %d (expected 2), writer %d (expected 0)\nserver: reader %d (expected 1), writer %d (expected 1)",
|
||||
trC.conn.(*transport).reader.seqNum,
|
||||
trC.conn.(*transport).writer.seqNum,
|
||||
trS.conn.(*transport).reader.seqNum,
|
||||
trS.conn.(*transport).writer.seqNum,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeqNumIncrease(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" {
|
||||
t.Skip("see golang.org/issue/7237")
|
||||
}
|
||||
|
||||
checker := &syncChecker{
|
||||
waitCall: make(chan int, 10),
|
||||
called: make(chan int, 10),
|
||||
}
|
||||
|
||||
checker.waitCall <- 1
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: checker.Check}, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshakePair: %v", err)
|
||||
}
|
||||
<-checker.called
|
||||
|
||||
t.Cleanup(func() {
|
||||
trC.Close()
|
||||
trS.Close()
|
||||
})
|
||||
|
||||
// Throw away the msgExtInfo packet sent during the handshake by the server
|
||||
_, err = trC.readPacket()
|
||||
if err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
}
|
||||
|
||||
// write and read five packets on either side to bump the sequence numbers
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := trC.writePacket([]byte{msgRequestSuccess}); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
if _, err := trS.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
}
|
||||
if err := trS.writePacket([]byte{msgRequestSuccess}); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
if _, err := trC.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
// close the handshake transports before checking the sequence number to
|
||||
// avoid races.
|
||||
trC.Close()
|
||||
trS.Close()
|
||||
|
||||
if trC.conn.(*transport).reader.seqNum != 7 || trC.conn.(*transport).writer.seqNum != 5 ||
|
||||
trS.conn.(*transport).reader.seqNum != 6 || trS.conn.(*transport).writer.seqNum != 6 {
|
||||
t.Errorf(
|
||||
"unexpected sequence counters:\nclient: reader %d (expected 7), writer %d (expected 5)\nserver: reader %d (expected 6), writer %d (expected 6)",
|
||||
trC.conn.(*transport).reader.seqNum,
|
||||
trC.conn.(*transport).writer.seqNum,
|
||||
trS.conn.(*transport).reader.seqNum,
|
||||
trS.conn.(*transport).writer.seqNum,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrictKEXUnexpectedMsg(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" {
|
||||
t.Skip("see golang.org/issue/7237")
|
||||
}
|
||||
|
||||
// Check that unexpected messages during the handshake cause failure
|
||||
_, _, err := handshakePair(&ClientConfig{HostKeyCallback: func(hostname string, remote net.Addr, key PublicKey) error { return nil }}, "addr", true)
|
||||
if err == nil {
|
||||
t.Fatal("handshake should fail when there are unexpected messages during the handshake")
|
||||
}
|
||||
|
||||
trC, trS, err := handshakePair(&ClientConfig{HostKeyCallback: func(hostname string, remote net.Addr, key PublicKey) error { return nil }}, "addr", false)
|
||||
if err != nil {
|
||||
t.Fatalf("handshake failed: %s", err)
|
||||
}
|
||||
|
||||
// Check that ignore/debug pacekts are still ignored outside of the handshake
|
||||
if err := trC.writePacket([]byte{msgIgnore}); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
if err := trC.writePacket([]byte{msgDebug}); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
dummyPacket := []byte{99}
|
||||
if err := trC.writePacket(dummyPacket); err != nil {
|
||||
t.Fatalf("writePacket failed: %s", err)
|
||||
}
|
||||
|
||||
if p, err := trS.readPacket(); err != nil {
|
||||
t.Fatalf("readPacket failed: %s", err)
|
||||
} else if !bytes.Equal(p, dummyPacket) {
|
||||
t.Fatalf("unexpected packet: got %x, want %x", p, dummyPacket)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrictKEXMixed(t *testing.T) {
|
||||
// Test that we still support a mixed connection, where one side sends kex-strict but the other
|
||||
// side doesn't.
|
||||
|
||||
a, b, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe failed: %s", err)
|
||||
}
|
||||
|
||||
var trC, trS keyingTransport
|
||||
|
||||
trC = newTransport(a, rand.Reader, true)
|
||||
trS = newTransport(b, rand.Reader, false)
|
||||
trS = addNoiseTransport(trS)
|
||||
|
||||
clientConf := &ClientConfig{HostKeyCallback: func(hostname string, remote net.Addr, key PublicKey) error { return nil }}
|
||||
clientConf.SetDefaults()
|
||||
|
||||
v := []byte("version")
|
||||
client := newClientTransport(trC, v, v, clientConf, "addr", a.RemoteAddr())
|
||||
|
||||
serverConf := &ServerConfig{}
|
||||
serverConf.AddHostKey(testSigners["ecdsa"])
|
||||
serverConf.AddHostKey(testSigners["rsa"])
|
||||
serverConf.SetDefaults()
|
||||
|
||||
transport := newHandshakeTransport(trS, &serverConf.Config, []byte("version"), []byte("version"))
|
||||
transport.hostKeys = serverConf.hostKeys
|
||||
transport.publicKeyAuthAlgorithms = serverConf.PublicKeyAuthAlgorithms
|
||||
|
||||
readOneFailure := make(chan error, 1)
|
||||
go func() {
|
||||
if _, err := transport.readOnePacket(true); err != nil {
|
||||
readOneFailure <- err
|
||||
}
|
||||
}()
|
||||
|
||||
// Basically sendKexInit, but without the kex-strict extension algorithm
|
||||
msg := &kexInitMsg{
|
||||
KexAlgos: transport.config.KeyExchanges,
|
||||
CiphersClientServer: transport.config.Ciphers,
|
||||
CiphersServerClient: transport.config.Ciphers,
|
||||
MACsClientServer: transport.config.MACs,
|
||||
MACsServerClient: transport.config.MACs,
|
||||
CompressionClientServer: supportedCompressions,
|
||||
CompressionServerClient: supportedCompressions,
|
||||
ServerHostKeyAlgos: []string{KeyAlgoRSASHA256, KeyAlgoRSASHA512, KeyAlgoRSA},
|
||||
}
|
||||
packet := Marshal(msg)
|
||||
// writePacket destroys the contents, so save a copy.
|
||||
packetCopy := make([]byte, len(packet))
|
||||
copy(packetCopy, packet)
|
||||
if err := transport.pushPacket(packetCopy); err != nil {
|
||||
t.Fatalf("pushPacket: %s", err)
|
||||
}
|
||||
transport.sentInitMsg = msg
|
||||
transport.sentInitPacket = packet
|
||||
|
||||
if err := transport.getWriteError(); err != nil {
|
||||
t.Fatalf("getWriteError failed: %s", err)
|
||||
}
|
||||
var request *pendingKex
|
||||
select {
|
||||
case err = <-readOneFailure:
|
||||
t.Fatalf("server readOnePacket failed: %s", err)
|
||||
case request = <-transport.startKex:
|
||||
break
|
||||
}
|
||||
|
||||
// We expect the following calls to fail if the side which does not support
|
||||
// kex-strict sends unexpected/ignored packets during the handshake, even if
|
||||
// the other side does support kex-strict.
|
||||
|
||||
if err := transport.enterKeyExchange(request.otherInit); err != nil {
|
||||
t.Fatalf("enterKeyExchange failed: %s", err)
|
||||
}
|
||||
if err := client.waitSession(); err != nil {
|
||||
t.Fatalf("client.waitSession: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
+17
-3
@@ -13,9 +13,10 @@ import (
|
||||
// An in-memory packetConn. It is safe to call Close and writePacket
|
||||
// from different goroutines.
|
||||
type memTransport struct {
|
||||
eof bool
|
||||
pending [][]byte
|
||||
write *memTransport
|
||||
eof bool
|
||||
pending [][]byte
|
||||
write *memTransport
|
||||
writeCount uint64
|
||||
sync.Mutex
|
||||
*sync.Cond
|
||||
}
|
||||
@@ -63,9 +64,16 @@ func (t *memTransport) writePacket(p []byte) error {
|
||||
copy(c, p)
|
||||
t.write.pending = append(t.write.pending, c)
|
||||
t.write.Cond.Signal()
|
||||
t.writeCount++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *memTransport) getWriteCount() uint64 {
|
||||
t.write.Lock()
|
||||
defer t.write.Unlock()
|
||||
return t.writeCount
|
||||
}
|
||||
|
||||
func memPipe() (a, b packetConn) {
|
||||
t1 := memTransport{}
|
||||
t2 := memTransport{}
|
||||
@@ -81,6 +89,9 @@ func TestMemPipe(t *testing.T) {
|
||||
if err := a.writePacket([]byte{42}); err != nil {
|
||||
t.Fatalf("writePacket: %v", err)
|
||||
}
|
||||
if wc := a.(*memTransport).getWriteCount(); wc != 1 {
|
||||
t.Fatalf("got %v, want 1", wc)
|
||||
}
|
||||
if err := a.Close(); err != nil {
|
||||
t.Fatal("Close: ", err)
|
||||
}
|
||||
@@ -95,6 +106,9 @@ func TestMemPipe(t *testing.T) {
|
||||
if err != io.EOF {
|
||||
t.Fatalf("got %v, %v, want EOF", p, err)
|
||||
}
|
||||
if wc := b.(*memTransport).getWriteCount(); wc != 0 {
|
||||
t.Fatalf("got %v, want 0", wc)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoubleClose(t *testing.T) {
|
||||
|
||||
@@ -182,6 +182,40 @@ func TestMuxChannelOverflow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMuxChannelReadUnblock(t *testing.T) {
|
||||
reader, writer, mux := channelPair(t)
|
||||
defer reader.Close()
|
||||
defer writer.Close()
|
||||
defer mux.Close()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
t.Cleanup(wg.Wait)
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
if _, err := writer.Write(make([]byte, channelWindowSize)); err != nil {
|
||||
t.Errorf("could not fill window: %v", err)
|
||||
}
|
||||
if _, err := writer.Write(make([]byte, 1)); err != nil {
|
||||
t.Errorf("Write: %v", err)
|
||||
}
|
||||
writer.Close()
|
||||
}()
|
||||
|
||||
writer.remoteWin.waitWriterBlocked()
|
||||
|
||||
buf := make([]byte, 32768)
|
||||
for {
|
||||
_, err := reader.Read(buf)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Read: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMuxChannelCloseWriteUnblock(t *testing.T) {
|
||||
reader, writer, mux := channelPair(t)
|
||||
defer reader.Close()
|
||||
@@ -754,6 +788,43 @@ func TestMuxMaxPacketSize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMuxChannelWindowDeferredUpdates(t *testing.T) {
|
||||
s, c, mux := channelPair(t)
|
||||
cTransport := mux.conn.(*memTransport)
|
||||
defer s.Close()
|
||||
defer c.Close()
|
||||
defer mux.Close()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
t.Cleanup(wg.Wait)
|
||||
|
||||
data := make([]byte, 1024)
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_, err := s.Write(data)
|
||||
if err != nil {
|
||||
t.Errorf("Write: %v", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
cWritesInit := cTransport.getWriteCount()
|
||||
buf := make([]byte, 1)
|
||||
for i := 0; i < len(data); i++ {
|
||||
n, err := c.Read(buf)
|
||||
if n != len(buf) || err != nil {
|
||||
t.Fatalf("Read: %v, %v", n, err)
|
||||
}
|
||||
}
|
||||
cWrites := cTransport.getWriteCount() - cWritesInit
|
||||
// reading 1 KiB should not cause any window updates to be sent, but allow
|
||||
// for some unexpected writes
|
||||
if cWrites > 30 {
|
||||
t.Fatalf("reading 1 KiB from channel caused %v writes", cWrites)
|
||||
}
|
||||
}
|
||||
|
||||
// Don't ship code with debug=true.
|
||||
func TestDebug(t *testing.T) {
|
||||
if debugMux {
|
||||
|
||||
@@ -213,6 +213,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
|
||||
} else {
|
||||
for _, algo := range fullConf.PublicKeyAuthAlgorithms {
|
||||
if !contains(supportedPubKeyAuthAlgos, algo) {
|
||||
c.Close()
|
||||
return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
|
||||
}
|
||||
}
|
||||
@@ -220,6 +221,7 @@ func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewCha
|
||||
// Check if the config contains any unsupported key exchanges
|
||||
for _, kex := range fullConf.KeyExchanges {
|
||||
if _, ok := serverForbiddenKexAlgos[kex]; ok {
|
||||
c.Close()
|
||||
return nil, nil, nil, fmt.Errorf("ssh: unsupported key exchange %s for server", kex)
|
||||
}
|
||||
}
|
||||
|
||||
+64
-9
@@ -5,7 +5,11 @@
|
||||
package ssh
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestClientAuthRestrictedPublicKeyAlgos(t *testing.T) {
|
||||
@@ -59,27 +63,78 @@ func TestClientAuthRestrictedPublicKeyAlgos(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewServerConnValidationErrors(t *testing.T) {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
|
||||
serverConf := &ServerConfig{
|
||||
PublicKeyAuthAlgorithms: []string{CertAlgoRSAv01},
|
||||
}
|
||||
_, _, _, err = NewServerConn(c1, serverConf)
|
||||
c := &markerConn{}
|
||||
_, _, _, err := NewServerConn(c, serverConf)
|
||||
if err == nil {
|
||||
t.Fatal("NewServerConn with invalid public key auth algorithms succeeded")
|
||||
}
|
||||
if !c.isClosed() {
|
||||
t.Fatal("NewServerConn with invalid public key auth algorithms left connection open")
|
||||
}
|
||||
if c.isUsed() {
|
||||
t.Fatal("NewServerConn with invalid public key auth algorithms used connection")
|
||||
}
|
||||
|
||||
serverConf = &ServerConfig{
|
||||
Config: Config{
|
||||
KeyExchanges: []string{kexAlgoDHGEXSHA256},
|
||||
},
|
||||
}
|
||||
_, _, _, err = NewServerConn(c1, serverConf)
|
||||
c = &markerConn{}
|
||||
_, _, _, err = NewServerConn(c, serverConf)
|
||||
if err == nil {
|
||||
t.Fatal("NewServerConn with unsupported key exchange succeeded")
|
||||
}
|
||||
if !c.isClosed() {
|
||||
t.Fatal("NewServerConn with unsupported key exchange left connection open")
|
||||
}
|
||||
if c.isUsed() {
|
||||
t.Fatal("NewServerConn with unsupported key exchange used connection")
|
||||
}
|
||||
}
|
||||
|
||||
type markerConn struct {
|
||||
closed uint32
|
||||
used uint32
|
||||
}
|
||||
|
||||
func (c *markerConn) isClosed() bool {
|
||||
return atomic.LoadUint32(&c.closed) != 0
|
||||
}
|
||||
|
||||
func (c *markerConn) isUsed() bool {
|
||||
return atomic.LoadUint32(&c.used) != 0
|
||||
}
|
||||
|
||||
func (c *markerConn) Close() error {
|
||||
atomic.StoreUint32(&c.closed, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *markerConn) Read(b []byte) (n int, err error) {
|
||||
atomic.StoreUint32(&c.used, 1)
|
||||
if atomic.LoadUint32(&c.closed) != 0 {
|
||||
return 0, net.ErrClosed
|
||||
} else {
|
||||
return 0, io.EOF
|
||||
}
|
||||
}
|
||||
|
||||
func (c *markerConn) Write(b []byte) (n int, err error) {
|
||||
atomic.StoreUint32(&c.used, 1)
|
||||
if atomic.LoadUint32(&c.closed) != 0 {
|
||||
return 0, net.ErrClosed
|
||||
} else {
|
||||
return 0, io.ErrClosedPipe
|
||||
}
|
||||
}
|
||||
|
||||
func (*markerConn) LocalAddr() net.Addr { return nil }
|
||||
func (*markerConn) RemoteAddr() net.Addr { return nil }
|
||||
|
||||
func (*markerConn) SetDeadline(t time.Time) error { return nil }
|
||||
func (*markerConn) SetReadDeadline(t time.Time) error { return nil }
|
||||
func (*markerConn) SetWriteDeadline(t time.Time) error { return nil }
|
||||
|
||||
@@ -34,6 +34,7 @@ func TestAgentForward(t *testing.T) {
|
||||
|
||||
sess, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("NewSession: %v", err)
|
||||
}
|
||||
if err := agent.RequestAgentForwarding(sess); err != nil {
|
||||
|
||||
@@ -53,6 +53,7 @@ func testDial(t *testing.T, n, listenAddr string, x dialTester) {
|
||||
// on the opened connection.
|
||||
cancel()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("Dial: %v", err)
|
||||
}
|
||||
x.TestClientConn(t, conn)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -27,6 +28,9 @@ func testPortForward(t *testing.T, n, listenAddr string) {
|
||||
|
||||
sshListener, err := conn.Listen(n, listenAddr)
|
||||
if err != nil {
|
||||
if runtime.GOOS == "darwin" && err == io.EOF {
|
||||
t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -122,6 +126,9 @@ func testAcceptClose(t *testing.T, n, listenAddr string) {
|
||||
|
||||
sshListener, err := conn.Listen(n, listenAddr)
|
||||
if err != nil {
|
||||
if runtime.GOOS == "darwin" && err == io.EOF {
|
||||
t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -163,6 +170,9 @@ func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) {
|
||||
|
||||
sshListener, err := client.Listen(n, listenAddr)
|
||||
if err != nil {
|
||||
if runtime.GOOS == "darwin" && err == io.EOF {
|
||||
t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,13 @@ import (
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func skipIfIssue64959(t *testing.T, err error) {
|
||||
if err != nil && runtime.GOOS == "darwin" && strings.Contains(err.Error(), "ssh: unexpected packet in response to channel open: <nil>") {
|
||||
t.Helper()
|
||||
t.Skipf("skipping test broken on some versions of macOS; see https://go.dev/issue/64959")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCommandSuccess(t *testing.T) {
|
||||
server := newServer(t)
|
||||
conn := server.Dial(clientConfig())
|
||||
@@ -29,6 +36,7 @@ func TestRunCommandSuccess(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("session failed: %v", err)
|
||||
}
|
||||
defer session.Close()
|
||||
@@ -66,6 +74,7 @@ func TestRunCommandStdin(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("session failed: %v", err)
|
||||
}
|
||||
defer session.Close()
|
||||
@@ -88,6 +97,7 @@ func TestRunCommandStdinError(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("session failed: %v", err)
|
||||
}
|
||||
defer session.Close()
|
||||
@@ -111,6 +121,7 @@ func TestRunCommandFailed(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("session failed: %v", err)
|
||||
}
|
||||
defer session.Close()
|
||||
@@ -127,6 +138,7 @@ func TestRunCommandWeClosed(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("session failed: %v", err)
|
||||
}
|
||||
err = session.Shell()
|
||||
@@ -146,6 +158,7 @@ func TestFuncLargeRead(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("unable to create new session: %s", err)
|
||||
}
|
||||
|
||||
@@ -182,6 +195,7 @@ func TestKeyChange(t *testing.T) {
|
||||
for i := 0; i < 4; i++ {
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("unable to create new session: %s", err)
|
||||
}
|
||||
|
||||
@@ -223,6 +237,7 @@ func TestValidTerminalMode(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("session failed: %v", err)
|
||||
}
|
||||
defer session.Close()
|
||||
@@ -287,6 +302,7 @@ func TestWindowChange(t *testing.T) {
|
||||
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("session failed: %v", err)
|
||||
}
|
||||
defer session.Close()
|
||||
@@ -349,6 +365,7 @@ func testOneCipher(t *testing.T, cipher string, cipherOrder []string) {
|
||||
// Exercise receiving data from the server
|
||||
session, err := conn.NewSession()
|
||||
if err != nil {
|
||||
skipIfIssue64959(t, err)
|
||||
t.Fatalf("NewSession: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ func (s *server) TryDial(config *ssh.ClientConfig) (*ssh.Client, error) {
|
||||
|
||||
// addr is the user specified host:port. While we don't actually dial it,
|
||||
// we need to know this for host key matching
|
||||
func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Client, error) {
|
||||
func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (client *ssh.Client, err error) {
|
||||
sshd, err := exec.LookPath("sshd")
|
||||
if err != nil {
|
||||
s.t.Skipf("skipping test: %v", err)
|
||||
@@ -188,13 +188,26 @@ func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Cl
|
||||
if err != nil {
|
||||
s.t.Fatalf("unixConnection: %v", err)
|
||||
}
|
||||
defer func() {
|
||||
// Close c2 after we've started the sshd command so that it won't prevent c1
|
||||
// from returning EOF when the sshd command exits.
|
||||
c2.Close()
|
||||
|
||||
// Leave c1 open if we're returning a client that wraps it.
|
||||
// (The client is responsible for closing it.)
|
||||
// Otherwise, close it to free up the socket.
|
||||
if client == nil {
|
||||
c1.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
cmd := testenv.Command(s.t, sshd, "-f", s.configfile, "-i", "-e")
|
||||
f, err := c2.File()
|
||||
if err != nil {
|
||||
s.t.Fatalf("UnixConn.File: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
cmd := testenv.Command(s.t, sshd, "-f", s.configfile, "-i", "-e")
|
||||
cmd.Stdin = f
|
||||
cmd.Stdout = f
|
||||
cmd.Stderr = new(bytes.Buffer)
|
||||
@@ -223,7 +236,7 @@ func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Cl
|
||||
// processes are killed too.
|
||||
cmd.Process.Signal(os.Interrupt)
|
||||
cmd.Wait()
|
||||
if s.t.Failed() {
|
||||
if s.t.Failed() || testing.Verbose() {
|
||||
// log any output from sshd process
|
||||
s.t.Logf("sshd:\n%s", cmd.Stderr)
|
||||
}
|
||||
|
||||
+27
-5
@@ -49,6 +49,9 @@ type transport struct {
|
||||
rand io.Reader
|
||||
isClient bool
|
||||
io.Closer
|
||||
|
||||
strictMode bool
|
||||
initialKEXDone bool
|
||||
}
|
||||
|
||||
// packetCipher represents a combination of SSH encryption/MAC
|
||||
@@ -74,6 +77,18 @@ type connectionState struct {
|
||||
pendingKeyChange chan packetCipher
|
||||
}
|
||||
|
||||
func (t *transport) setStrictMode() error {
|
||||
if t.reader.seqNum != 1 {
|
||||
return errors.New("ssh: sequence number != 1 when strict KEX mode requested")
|
||||
}
|
||||
t.strictMode = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *transport) setInitialKEXDone() {
|
||||
t.initialKEXDone = true
|
||||
}
|
||||
|
||||
// prepareKeyChange sets up key material for a keychange. The key changes in
|
||||
// both directions are triggered by reading and writing a msgNewKey packet
|
||||
// respectively.
|
||||
@@ -112,11 +127,12 @@ func (t *transport) printPacket(p []byte, write bool) {
|
||||
// Read and decrypt next packet.
|
||||
func (t *transport) readPacket() (p []byte, err error) {
|
||||
for {
|
||||
p, err = t.reader.readPacket(t.bufReader)
|
||||
p, err = t.reader.readPacket(t.bufReader, t.strictMode)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if len(p) == 0 || (p[0] != msgIgnore && p[0] != msgDebug) {
|
||||
// in strict mode we pass through DEBUG and IGNORE packets only during the initial KEX
|
||||
if len(p) == 0 || (t.strictMode && !t.initialKEXDone) || (p[0] != msgIgnore && p[0] != msgDebug) {
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -127,7 +143,7 @@ func (t *transport) readPacket() (p []byte, err error) {
|
||||
return p, err
|
||||
}
|
||||
|
||||
func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
|
||||
func (s *connectionState) readPacket(r *bufio.Reader, strictMode bool) ([]byte, error) {
|
||||
packet, err := s.packetCipher.readCipherPacket(s.seqNum, r)
|
||||
s.seqNum++
|
||||
if err == nil && len(packet) == 0 {
|
||||
@@ -140,6 +156,9 @@ func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) {
|
||||
select {
|
||||
case cipher := <-s.pendingKeyChange:
|
||||
s.packetCipher = cipher
|
||||
if strictMode {
|
||||
s.seqNum = 0
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("ssh: got bogus newkeys message")
|
||||
}
|
||||
@@ -170,10 +189,10 @@ func (t *transport) writePacket(packet []byte) error {
|
||||
if debugTransport {
|
||||
t.printPacket(packet, true)
|
||||
}
|
||||
return t.writer.writePacket(t.bufWriter, t.rand, packet)
|
||||
return t.writer.writePacket(t.bufWriter, t.rand, packet, t.strictMode)
|
||||
}
|
||||
|
||||
func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error {
|
||||
func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte, strictMode bool) error {
|
||||
changeKeys := len(packet) > 0 && packet[0] == msgNewKeys
|
||||
|
||||
err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet)
|
||||
@@ -188,6 +207,9 @@ func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []
|
||||
select {
|
||||
case cipher := <-s.pendingKeyChange:
|
||||
s.packetCipher = cipher
|
||||
if strictMode {
|
||||
s.seqNum = 0
|
||||
}
|
||||
default:
|
||||
panic("ssh: no key material for msgNewKeys")
|
||||
}
|
||||
|
||||
+202
-59
@@ -446,43 +446,6 @@ f9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpfNIbnYrX9
|
||||
ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNK
|
||||
GbqEZycPvEJdvSRUDewdcAZfpLz6IHxV
|
||||
-----END CERTIFICATE-----
|
||||
# CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES
|
||||
# 04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
|
||||
-----END CERTIFICATE-----
|
||||
# CN=BJCA Global Root CA1,O=BEIJING CERTIFICATE AUTHORITY,C=CN
|
||||
# f3896f88fe7c0a882766a7fa6ad2749fb57a7f3e98fb769c1fa7b09c2c44d5ae
|
||||
-----BEGIN CERTIFICATE-----
|
||||
@@ -992,6 +955,104 @@ qJZ9ZPskWkoDbGs4xugDQ5r3V7mzKWmTOPQD8rv7gmsHINFSH5pkAnuYZttcTVoP
|
||||
0ISVoDwUQwbKytu4QTbaakRnh6+v40URFWkIsr4WOZckbxJF0WddCajJFdr60qZf
|
||||
E2Efv4WstK2tBZQIgx51F9NxO5NQI1mg7TyRVJ12AMXDuDjb
|
||||
-----END CERTIFICATE-----
|
||||
# CN=CommScope Public Trust ECC Root-01,O=CommScope,C=US
|
||||
# 11437cda7bb45e41365f45b39a38986b0de00def348e0c7bb0873633800bc38b
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMw
|
||||
TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t
|
||||
bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNa
|
||||
Fw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv
|
||||
cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDEw
|
||||
djAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLxeP0C
|
||||
flfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJE
|
||||
hRGnSjot6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
|
||||
VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggq
|
||||
hkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg
|
||||
2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liWpDVfG2XqYZpwI7UNo5uS
|
||||
Um9poIyNStDuiw7LR47QjRE=
|
||||
-----END CERTIFICATE-----
|
||||
# CN=CommScope Public Trust ECC Root-02,O=CommScope,C=US
|
||||
# 2ffb7f813bbbb3c89ab4e8162d0f16d71509a830cc9d73c262e5140875d1ad4a
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMw
|
||||
TjELMAkGA1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29t
|
||||
bVNjb3BlIFB1YmxpYyBUcnVzdCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRa
|
||||
Fw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlDb21tU2Nv
|
||||
cGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3QgRUNDIFJvb3QtMDIw
|
||||
djAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/MMDAL
|
||||
j2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmU
|
||||
v4RDsNuESgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
|
||||
VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggq
|
||||
hkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/n
|
||||
ich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs73u1Z/GtMMH9ZzkXpc2AV
|
||||
mkzw5l4lIhVtwodZ0LKOag==
|
||||
-----END CERTIFICATE-----
|
||||
# CN=CommScope Public Trust RSA Root-01,O=CommScope,C=US
|
||||
# 02bdf96e2a45dd9bf18fc7e1dbdf21a0379ba3c9c2610344cfd8d606fec1ed81
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
# CN=CommScope Public Trust RSA Root-02,O=CommScope,C=US
|
||||
# ffe943d793424b4f7c440c1c3d648d5363f34b82dc87aa7a9f118fc5dee101f1
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
-----END CERTIFICATE-----
|
||||
# CN=D-TRUST BR Root CA 1 2020,O=D-Trust GmbH,C=DE
|
||||
# e59aaa816009c22bff5b25bad37df306f049797c1f81d85ab089e657bd8f0044
|
||||
-----BEGIN CERTIFICATE-----
|
||||
@@ -3101,6 +3162,58 @@ lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
|
||||
aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
|
||||
YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
|
||||
-----END CERTIFICATE-----
|
||||
# CN=Telekom Security TLS ECC Root 2020,O=Deutsche Telekom Security GmbH,C=DE
|
||||
# 578af4ded0853f4e5998db4aeaf9cbea8d945f60b620a38d1a3c13b2bc7ba8e1
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICQjCCAcmgAwIBAgIQNjqWjMlcsljN0AFdxeVXADAKBggqhkjOPQQDAzBjMQsw
|
||||
CQYDVQQGEwJERTEnMCUGA1UECgweRGV1dHNjaGUgVGVsZWtvbSBTZWN1cml0eSBH
|
||||
bWJIMSswKQYDVQQDDCJUZWxla29tIFNlY3VyaXR5IFRMUyBFQ0MgUm9vdCAyMDIw
|
||||
MB4XDTIwMDgyNTA3NDgyMFoXDTQ1MDgyNTIzNTk1OVowYzELMAkGA1UEBhMCREUx
|
||||
JzAlBgNVBAoMHkRldXRzY2hlIFRlbGVrb20gU2VjdXJpdHkgR21iSDErMCkGA1UE
|
||||
AwwiVGVsZWtvbSBTZWN1cml0eSBUTFMgRUNDIFJvb3QgMjAyMDB2MBAGByqGSM49
|
||||
AgEGBSuBBAAiA2IABM6//leov9Wq9xCazbzREaK9Z0LMkOsVGJDZos0MKiXrPk/O
|
||||
tdKPD/M12kOLAoC+b1EkHQ9rK8qfwm9QMuU3ILYg/4gND21Ju9sGpIeQkpT0CdDP
|
||||
f8iAC8GXs7s1J8nCG6NCMEAwHQYDVR0OBBYEFONyzG6VmUex5rNhTNHLq+O6zd6f
|
||||
MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA
|
||||
MGQCMHVSi7ekEE+uShCLsoRbQuHmKjYC2qBuGT8lv9pZMo7k+5Dck2TOrbRBR2Di
|
||||
z6fLHgIwN0GMZt9Ba9aDAEH9L1r3ULRn0SyocddDypwnJJGDSA3PzfdUga/sf+Rn
|
||||
27iQ7t0l
|
||||
-----END CERTIFICATE-----
|
||||
# CN=Telekom Security TLS RSA Root 2023,O=Deutsche Telekom Security GmbH,C=DE
|
||||
# efc65cadbb59adb6efe84da22311b35624b71b3b1ea0da8b6655174ec8978646
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
dTdmQRCsu/WU48IxK63nI1bMNSWSs1A=
|
||||
-----END CERTIFICATE-----
|
||||
# CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI
|
||||
# 242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c
|
||||
-----BEGIN CERTIFICATE-----
|
||||
@@ -3167,6 +3280,58 @@ t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
|
||||
HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
|
||||
SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
|
||||
-----END CERTIFICATE-----
|
||||
# CN=TrustAsia Global Root CA G3,O=TrustAsia Technologies\, Inc.,C=CN
|
||||
# e0d3226aeb1163c2e48ff9be3b50b4c6431be7bb1eacc5c36b5d5ec509039a08
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
FGWsJwt0ivKH
|
||||
-----END CERTIFICATE-----
|
||||
# CN=TrustAsia Global Root CA G4,O=TrustAsia Technologies\, Inc.,C=CN
|
||||
# be4b56cb5056c0136a526df444508daa36a0b54f42e4ac38f72af470e479654c
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMw
|
||||
WjELMAkGA1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMs
|
||||
IEluYy4xJDAiBgNVBAMMG1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0y
|
||||
MTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJaMFoxCzAJBgNVBAYTAkNOMSUwIwYD
|
||||
VQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQDDBtUcnVz
|
||||
dEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATx
|
||||
s8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbw
|
||||
LxYI+hW8m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJij
|
||||
YzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mD
|
||||
pm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/pDHel4NZg6ZvccveMA4GA1UdDwEB/wQE
|
||||
AwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AAbbd+NvBNEU/zy4k6LHiR
|
||||
UKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xkdUfFVZDj
|
||||
/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA==
|
||||
-----END CERTIFICATE-----
|
||||
# CN=Trustwave Global Certification Authority,O=Trustwave Holdings\, Inc.,L=Chicago,ST=Illinois,C=US
|
||||
# 97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8
|
||||
-----BEGIN CERTIFICATE-----
|
||||
@@ -3627,28 +3792,6 @@ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
|
||||
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
|
||||
ReYNnyicsbkqWletNw+vHX/bvZ8=
|
||||
-----END CERTIFICATE-----
|
||||
# OU=Security Communication RootCA1,O=SECOM Trust.net,C=JP
|
||||
# e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY
|
||||
MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t
|
||||
dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5
|
||||
WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD
|
||||
VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8
|
||||
9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ
|
||||
DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9
|
||||
Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N
|
||||
QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ
|
||||
xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G
|
||||
A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T
|
||||
AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG
|
||||
kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr
|
||||
Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5
|
||||
Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU
|
||||
JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
|
||||
RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
|
||||
-----END CERTIFICATE-----
|
||||
# OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\,LTD.,C=JP
|
||||
# 513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6
|
||||
-----BEGIN CERTIFICATE-----
|
||||
|
||||
Reference in New Issue
Block a user