Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d042a396a6 | ||
|
|
b92bf9480d | ||
|
|
6f79b5a20c | ||
|
|
8d0d405eed | ||
|
|
b91329d961 | ||
|
|
7067223927 | ||
|
|
0d2316b267 | ||
|
|
0aab8d07ae | ||
|
|
5bead598a0 | ||
|
|
1a865804d5 | ||
|
|
1c981e6f81 | ||
|
|
62c9f1799c | ||
|
|
405cb3bdea | ||
|
|
913d3ae741 | ||
|
|
dbb6ec16ec | ||
|
|
403f69900e | ||
|
|
055043dfed | ||
|
|
08396bb92b |
+52
-58
@@ -33,6 +33,9 @@
|
|||||||
#define CONSTBASE R16
|
#define CONSTBASE R16
|
||||||
#define BLOCKS R17
|
#define BLOCKS R17
|
||||||
|
|
||||||
|
// for VPERMXOR
|
||||||
|
#define MASK R18
|
||||||
|
|
||||||
DATA consts<>+0x00(SB)/8, $0x3320646e61707865
|
DATA consts<>+0x00(SB)/8, $0x3320646e61707865
|
||||||
DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
|
DATA consts<>+0x08(SB)/8, $0x6b20657479622d32
|
||||||
DATA consts<>+0x10(SB)/8, $0x0000000000000001
|
DATA consts<>+0x10(SB)/8, $0x0000000000000001
|
||||||
@@ -53,7 +56,11 @@ DATA consts<>+0x80(SB)/8, $0x6b2065746b206574
|
|||||||
DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
|
DATA consts<>+0x88(SB)/8, $0x6b2065746b206574
|
||||||
DATA consts<>+0x90(SB)/8, $0x0000000100000000
|
DATA consts<>+0x90(SB)/8, $0x0000000100000000
|
||||||
DATA consts<>+0x98(SB)/8, $0x0000000300000002
|
DATA consts<>+0x98(SB)/8, $0x0000000300000002
|
||||||
GLOBL consts<>(SB), RODATA, $0xa0
|
DATA consts<>+0xa0(SB)/8, $0x5566774411223300
|
||||||
|
DATA consts<>+0xa8(SB)/8, $0xddeeffcc99aabb88
|
||||||
|
DATA consts<>+0xb0(SB)/8, $0x6677445522330011
|
||||||
|
DATA consts<>+0xb8(SB)/8, $0xeeffccddaabb8899
|
||||||
|
GLOBL consts<>(SB), RODATA, $0xc0
|
||||||
|
|
||||||
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
//func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
|
||||||
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
||||||
@@ -70,6 +77,9 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
|||||||
MOVD $48, R10
|
MOVD $48, R10
|
||||||
MOVD $64, R11
|
MOVD $64, R11
|
||||||
SRD $6, LEN, BLOCKS
|
SRD $6, LEN, BLOCKS
|
||||||
|
// for VPERMXOR
|
||||||
|
MOVD $consts<>+0xa0(SB), MASK
|
||||||
|
MOVD $16, R20
|
||||||
// V16
|
// V16
|
||||||
LXVW4X (CONSTBASE)(R0), VS48
|
LXVW4X (CONSTBASE)(R0), VS48
|
||||||
ADD $80,CONSTBASE
|
ADD $80,CONSTBASE
|
||||||
@@ -87,6 +97,10 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
|||||||
// V28
|
// V28
|
||||||
LXVW4X (CONSTBASE)(R11), VS60
|
LXVW4X (CONSTBASE)(R11), VS60
|
||||||
|
|
||||||
|
// Load mask constants for VPERMXOR
|
||||||
|
LXVW4X (MASK)(R0), V20
|
||||||
|
LXVW4X (MASK)(R20), V21
|
||||||
|
|
||||||
// splat slot from V19 -> V26
|
// splat slot from V19 -> V26
|
||||||
VSPLTW $0, V19, V26
|
VSPLTW $0, V19, V26
|
||||||
|
|
||||||
@@ -97,7 +111,7 @@ TEXT ·chaCha20_ctr32_vsx(SB),NOSPLIT,$64-40
|
|||||||
|
|
||||||
MOVD $10, R14
|
MOVD $10, R14
|
||||||
MOVD R14, CTR
|
MOVD R14, CTR
|
||||||
|
PCALIGN $16
|
||||||
loop_outer_vsx:
|
loop_outer_vsx:
|
||||||
// V0, V1, V2, V3
|
// V0, V1, V2, V3
|
||||||
LXVW4X (R0)(CONSTBASE), VS32
|
LXVW4X (R0)(CONSTBASE), VS32
|
||||||
@@ -128,22 +142,17 @@ loop_outer_vsx:
|
|||||||
VSPLTISW $12, V28
|
VSPLTISW $12, V28
|
||||||
VSPLTISW $8, V29
|
VSPLTISW $8, V29
|
||||||
VSPLTISW $7, V30
|
VSPLTISW $7, V30
|
||||||
|
PCALIGN $16
|
||||||
loop_vsx:
|
loop_vsx:
|
||||||
VADDUWM V0, V4, V0
|
VADDUWM V0, V4, V0
|
||||||
VADDUWM V1, V5, V1
|
VADDUWM V1, V5, V1
|
||||||
VADDUWM V2, V6, V2
|
VADDUWM V2, V6, V2
|
||||||
VADDUWM V3, V7, V3
|
VADDUWM V3, V7, V3
|
||||||
|
|
||||||
VXOR V12, V0, V12
|
VPERMXOR V12, V0, V21, V12
|
||||||
VXOR V13, V1, V13
|
VPERMXOR V13, V1, V21, V13
|
||||||
VXOR V14, V2, V14
|
VPERMXOR V14, V2, V21, V14
|
||||||
VXOR V15, V3, V15
|
VPERMXOR V15, V3, V21, V15
|
||||||
|
|
||||||
VRLW V12, V27, V12
|
|
||||||
VRLW V13, V27, V13
|
|
||||||
VRLW V14, V27, V14
|
|
||||||
VRLW V15, V27, V15
|
|
||||||
|
|
||||||
VADDUWM V8, V12, V8
|
VADDUWM V8, V12, V8
|
||||||
VADDUWM V9, V13, V9
|
VADDUWM V9, V13, V9
|
||||||
@@ -165,15 +174,10 @@ loop_vsx:
|
|||||||
VADDUWM V2, V6, V2
|
VADDUWM V2, V6, V2
|
||||||
VADDUWM V3, V7, V3
|
VADDUWM V3, V7, V3
|
||||||
|
|
||||||
VXOR V12, V0, V12
|
VPERMXOR V12, V0, V20, V12
|
||||||
VXOR V13, V1, V13
|
VPERMXOR V13, V1, V20, V13
|
||||||
VXOR V14, V2, V14
|
VPERMXOR V14, V2, V20, V14
|
||||||
VXOR V15, V3, V15
|
VPERMXOR V15, V3, V20, V15
|
||||||
|
|
||||||
VRLW V12, V29, V12
|
|
||||||
VRLW V13, V29, V13
|
|
||||||
VRLW V14, V29, V14
|
|
||||||
VRLW V15, V29, V15
|
|
||||||
|
|
||||||
VADDUWM V8, V12, V8
|
VADDUWM V8, V12, V8
|
||||||
VADDUWM V9, V13, V9
|
VADDUWM V9, V13, V9
|
||||||
@@ -195,15 +199,10 @@ loop_vsx:
|
|||||||
VADDUWM V2, V7, V2
|
VADDUWM V2, V7, V2
|
||||||
VADDUWM V3, V4, V3
|
VADDUWM V3, V4, V3
|
||||||
|
|
||||||
VXOR V15, V0, V15
|
VPERMXOR V15, V0, V21, V15
|
||||||
VXOR V12, V1, V12
|
VPERMXOR V12, V1, V21, V12
|
||||||
VXOR V13, V2, V13
|
VPERMXOR V13, V2, V21, V13
|
||||||
VXOR V14, V3, V14
|
VPERMXOR V14, V3, V21, V14
|
||||||
|
|
||||||
VRLW V15, V27, V15
|
|
||||||
VRLW V12, V27, V12
|
|
||||||
VRLW V13, V27, V13
|
|
||||||
VRLW V14, V27, V14
|
|
||||||
|
|
||||||
VADDUWM V10, V15, V10
|
VADDUWM V10, V15, V10
|
||||||
VADDUWM V11, V12, V11
|
VADDUWM V11, V12, V11
|
||||||
@@ -225,15 +224,10 @@ loop_vsx:
|
|||||||
VADDUWM V2, V7, V2
|
VADDUWM V2, V7, V2
|
||||||
VADDUWM V3, V4, V3
|
VADDUWM V3, V4, V3
|
||||||
|
|
||||||
VXOR V15, V0, V15
|
VPERMXOR V15, V0, V20, V15
|
||||||
VXOR V12, V1, V12
|
VPERMXOR V12, V1, V20, V12
|
||||||
VXOR V13, V2, V13
|
VPERMXOR V13, V2, V20, V13
|
||||||
VXOR V14, V3, V14
|
VPERMXOR V14, V3, V20, V14
|
||||||
|
|
||||||
VRLW V15, V29, V15
|
|
||||||
VRLW V12, V29, V12
|
|
||||||
VRLW V13, V29, V13
|
|
||||||
VRLW V14, V29, V14
|
|
||||||
|
|
||||||
VADDUWM V10, V15, V10
|
VADDUWM V10, V15, V10
|
||||||
VADDUWM V11, V12, V11
|
VADDUWM V11, V12, V11
|
||||||
@@ -249,48 +243,48 @@ loop_vsx:
|
|||||||
VRLW V6, V30, V6
|
VRLW V6, V30, V6
|
||||||
VRLW V7, V30, V7
|
VRLW V7, V30, V7
|
||||||
VRLW V4, V30, V4
|
VRLW V4, V30, V4
|
||||||
BC 16, LT, loop_vsx
|
BDNZ loop_vsx
|
||||||
|
|
||||||
VADDUWM V12, V26, V12
|
VADDUWM V12, V26, V12
|
||||||
|
|
||||||
WORD $0x13600F8C // VMRGEW V0, V1, V27
|
VMRGEW V0, V1, V27
|
||||||
WORD $0x13821F8C // VMRGEW V2, V3, V28
|
VMRGEW V2, V3, V28
|
||||||
|
|
||||||
WORD $0x10000E8C // VMRGOW V0, V1, V0
|
VMRGOW V0, V1, V0
|
||||||
WORD $0x10421E8C // VMRGOW V2, V3, V2
|
VMRGOW V2, V3, V2
|
||||||
|
|
||||||
WORD $0x13A42F8C // VMRGEW V4, V5, V29
|
VMRGEW V4, V5, V29
|
||||||
WORD $0x13C63F8C // VMRGEW V6, V7, V30
|
VMRGEW V6, V7, V30
|
||||||
|
|
||||||
XXPERMDI VS32, VS34, $0, VS33
|
XXPERMDI VS32, VS34, $0, VS33
|
||||||
XXPERMDI VS32, VS34, $3, VS35
|
XXPERMDI VS32, VS34, $3, VS35
|
||||||
XXPERMDI VS59, VS60, $0, VS32
|
XXPERMDI VS59, VS60, $0, VS32
|
||||||
XXPERMDI VS59, VS60, $3, VS34
|
XXPERMDI VS59, VS60, $3, VS34
|
||||||
|
|
||||||
WORD $0x10842E8C // VMRGOW V4, V5, V4
|
VMRGOW V4, V5, V4
|
||||||
WORD $0x10C63E8C // VMRGOW V6, V7, V6
|
VMRGOW V6, V7, V6
|
||||||
|
|
||||||
WORD $0x13684F8C // VMRGEW V8, V9, V27
|
VMRGEW V8, V9, V27
|
||||||
WORD $0x138A5F8C // VMRGEW V10, V11, V28
|
VMRGEW V10, V11, V28
|
||||||
|
|
||||||
XXPERMDI VS36, VS38, $0, VS37
|
XXPERMDI VS36, VS38, $0, VS37
|
||||||
XXPERMDI VS36, VS38, $3, VS39
|
XXPERMDI VS36, VS38, $3, VS39
|
||||||
XXPERMDI VS61, VS62, $0, VS36
|
XXPERMDI VS61, VS62, $0, VS36
|
||||||
XXPERMDI VS61, VS62, $3, VS38
|
XXPERMDI VS61, VS62, $3, VS38
|
||||||
|
|
||||||
WORD $0x11084E8C // VMRGOW V8, V9, V8
|
VMRGOW V8, V9, V8
|
||||||
WORD $0x114A5E8C // VMRGOW V10, V11, V10
|
VMRGOW V10, V11, V10
|
||||||
|
|
||||||
WORD $0x13AC6F8C // VMRGEW V12, V13, V29
|
VMRGEW V12, V13, V29
|
||||||
WORD $0x13CE7F8C // VMRGEW V14, V15, V30
|
VMRGEW V14, V15, V30
|
||||||
|
|
||||||
XXPERMDI VS40, VS42, $0, VS41
|
XXPERMDI VS40, VS42, $0, VS41
|
||||||
XXPERMDI VS40, VS42, $3, VS43
|
XXPERMDI VS40, VS42, $3, VS43
|
||||||
XXPERMDI VS59, VS60, $0, VS40
|
XXPERMDI VS59, VS60, $0, VS40
|
||||||
XXPERMDI VS59, VS60, $3, VS42
|
XXPERMDI VS59, VS60, $3, VS42
|
||||||
|
|
||||||
WORD $0x118C6E8C // VMRGOW V12, V13, V12
|
VMRGOW V12, V13, V12
|
||||||
WORD $0x11CE7E8C // VMRGOW V14, V15, V14
|
VMRGOW V14, V15, V14
|
||||||
|
|
||||||
VSPLTISW $4, V27
|
VSPLTISW $4, V27
|
||||||
VADDUWM V26, V27, V26
|
VADDUWM V26, V27, V26
|
||||||
@@ -431,7 +425,7 @@ tail_vsx:
|
|||||||
ADD $-1, R11, R12
|
ADD $-1, R11, R12
|
||||||
ADD $-1, INP
|
ADD $-1, INP
|
||||||
ADD $-1, OUT
|
ADD $-1, OUT
|
||||||
|
PCALIGN $16
|
||||||
looptail_vsx:
|
looptail_vsx:
|
||||||
// Copying the result to OUT
|
// Copying the result to OUT
|
||||||
// in bytes.
|
// in bytes.
|
||||||
@@ -439,7 +433,7 @@ looptail_vsx:
|
|||||||
MOVBZU 1(INP), TMP
|
MOVBZU 1(INP), TMP
|
||||||
XOR KEY, TMP, KEY
|
XOR KEY, TMP, KEY
|
||||||
MOVBU KEY, 1(OUT)
|
MOVBU KEY, 1(OUT)
|
||||||
BC 16, LT, looptail_vsx
|
BDNZ looptail_vsx
|
||||||
|
|
||||||
// Clear the stack values
|
// Clear the stack values
|
||||||
STXVW4X VS48, (R11)(R0)
|
STXVW4X VS48, (R11)(R0)
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ module golang.org/x/crypto
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/net v0.10.0 // tagx:ignore
|
golang.org/x/net v0.21.0 // tagx:ignore
|
||||||
golang.org/x/sys v0.15.0
|
golang.org/x/sys v0.19.0
|
||||||
golang.org/x/term v0.15.0
|
golang.org/x/term v0.19.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require golang.org/x/text v0.14.0 // indirect
|
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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.19.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.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
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
|
package poly1305
|
||||||
|
|
||||||
import "encoding/binary"
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"math/bits"
|
||||||
|
)
|
||||||
|
|
||||||
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag
|
// Poly1305 [RFC 7539] is a relatively simple algorithm: the authentication tag
|
||||||
// for a 64 bytes message is approximately
|
// for a 64 bytes message is approximately
|
||||||
@@ -114,13 +117,13 @@ type uint128 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mul64(a, b uint64) uint128 {
|
func mul64(a, b uint64) uint128 {
|
||||||
hi, lo := bitsMul64(a, b)
|
hi, lo := bits.Mul64(a, b)
|
||||||
return uint128{lo, hi}
|
return uint128{lo, hi}
|
||||||
}
|
}
|
||||||
|
|
||||||
func add128(a, b uint128) uint128 {
|
func add128(a, b uint128) uint128 {
|
||||||
lo, c := bitsAdd64(a.lo, b.lo, 0)
|
lo, c := bits.Add64(a.lo, b.lo, 0)
|
||||||
hi, c := bitsAdd64(a.hi, b.hi, c)
|
hi, c := bits.Add64(a.hi, b.hi, c)
|
||||||
if c != 0 {
|
if c != 0 {
|
||||||
panic("poly1305: unexpected overflow")
|
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
|
// hide leading zeroes. For full chunks, that's 1 << 128, so we can just
|
||||||
// add 1 to the most significant (2¹²⁸) limb, h2.
|
// add 1 to the most significant (2¹²⁸) limb, h2.
|
||||||
if len(msg) >= TagSize {
|
if len(msg) >= TagSize {
|
||||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(msg[0:8]), 0)
|
||||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(msg[8:16]), c)
|
||||||
h2 += c + 1
|
h2 += c + 1
|
||||||
|
|
||||||
msg = msg[TagSize:]
|
msg = msg[TagSize:]
|
||||||
@@ -165,8 +168,8 @@ func updateGeneric(state *macState, msg []byte) {
|
|||||||
copy(buf[:], msg)
|
copy(buf[:], msg)
|
||||||
buf[len(msg)] = 1
|
buf[len(msg)] = 1
|
||||||
|
|
||||||
h0, c = bitsAdd64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
h0, c = bits.Add64(h0, binary.LittleEndian.Uint64(buf[0:8]), 0)
|
||||||
h1, c = bitsAdd64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
h1, c = bits.Add64(h1, binary.LittleEndian.Uint64(buf[8:16]), c)
|
||||||
h2 += c
|
h2 += c
|
||||||
|
|
||||||
msg = nil
|
msg = nil
|
||||||
@@ -219,9 +222,9 @@ func updateGeneric(state *macState, msg []byte) {
|
|||||||
m3 := h2r1
|
m3 := h2r1
|
||||||
|
|
||||||
t0 := m0.lo
|
t0 := m0.lo
|
||||||
t1, c := bitsAdd64(m1.lo, m0.hi, 0)
|
t1, c := bits.Add64(m1.lo, m0.hi, 0)
|
||||||
t2, c := bitsAdd64(m2.lo, m1.hi, c)
|
t2, c := bits.Add64(m2.lo, m1.hi, c)
|
||||||
t3, _ := bitsAdd64(m3.lo, m2.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
|
// 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
|
// 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.
|
// 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)
|
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
h1, c = bits.Add64(h1, cc.hi, c)
|
||||||
h2 += c
|
h2 += c
|
||||||
|
|
||||||
cc = shiftRightBy2(cc)
|
cc = shiftRightBy2(cc)
|
||||||
|
|
||||||
h0, c = bitsAdd64(h0, cc.lo, 0)
|
h0, c = bits.Add64(h0, cc.lo, 0)
|
||||||
h1, c = bitsAdd64(h1, cc.hi, c)
|
h1, c = bits.Add64(h1, cc.hi, c)
|
||||||
h2 += c
|
h2 += c
|
||||||
|
|
||||||
// h2 is at most 3 + 1 + 1 = 5, making the whole of h at most
|
// 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
|
// in constant time, we compute t = h - (2¹³⁰ - 5), and select h as the
|
||||||
// result if the subtraction underflows, and t otherwise.
|
// result if the subtraction underflows, and t otherwise.
|
||||||
|
|
||||||
hMinusP0, b := bitsSub64(h0, p0, 0)
|
hMinusP0, b := bits.Sub64(h0, p0, 0)
|
||||||
hMinusP1, b := bitsSub64(h1, p1, b)
|
hMinusP1, b := bits.Sub64(h1, p1, b)
|
||||||
_, b = bitsSub64(h2, p2, b)
|
_, b = bits.Sub64(h2, p2, b)
|
||||||
|
|
||||||
// h = h if h < p else h - p
|
// h = h if h < p else h - p
|
||||||
h0 = select64(b, h0, hMinusP0)
|
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
|
// by just doing a wide addition with the 128 low bits of h and discarding
|
||||||
// the overflow.
|
// the overflow.
|
||||||
h0, c := bitsAdd64(h0, s[0], 0)
|
h0, c := bits.Add64(h0, s[0], 0)
|
||||||
h1, _ = bitsAdd64(h1, s[1], c)
|
h1, _ = bits.Add64(h1, s[1], c)
|
||||||
|
|
||||||
binary.LittleEndian.PutUint64(out[0:8], h0)
|
binary.LittleEndian.PutUint64(out[0:8], h0)
|
||||||
binary.LittleEndian.PutUint64(out[8:16], h1)
|
binary.LittleEndian.PutUint64(out[8:16], h1)
|
||||||
|
|||||||
@@ -19,15 +19,14 @@
|
|||||||
|
|
||||||
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
|
#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3, t4, t5) \
|
||||||
MULLD r0, h0, t0; \
|
MULLD r0, h0, t0; \
|
||||||
MULLD r0, h1, t4; \
|
|
||||||
MULHDU r0, h0, t1; \
|
MULHDU r0, h0, t1; \
|
||||||
|
MULLD r0, h1, t4; \
|
||||||
MULHDU r0, h1, t5; \
|
MULHDU r0, h1, t5; \
|
||||||
ADDC t4, t1, t1; \
|
ADDC t4, t1, t1; \
|
||||||
MULLD r0, h2, t2; \
|
MULLD r0, h2, t2; \
|
||||||
ADDZE t5; \
|
|
||||||
MULHDU r1, h0, t4; \
|
MULHDU r1, h0, t4; \
|
||||||
MULLD r1, h0, h0; \
|
MULLD r1, h0, h0; \
|
||||||
ADD t5, t2, t2; \
|
ADDE t5, t2, t2; \
|
||||||
ADDC h0, t1, t1; \
|
ADDC h0, t1, t1; \
|
||||||
MULLD h2, r1, t3; \
|
MULLD h2, r1, t3; \
|
||||||
ADDZE t4, h0; \
|
ADDZE t4, h0; \
|
||||||
@@ -37,13 +36,11 @@
|
|||||||
ADDE t5, t3, t3; \
|
ADDE t5, t3, t3; \
|
||||||
ADDC h0, t2, t2; \
|
ADDC h0, t2, t2; \
|
||||||
MOVD $-4, t4; \
|
MOVD $-4, t4; \
|
||||||
MOVD t0, h0; \
|
|
||||||
MOVD t1, h1; \
|
|
||||||
ADDZE t3; \
|
ADDZE t3; \
|
||||||
ANDCC $3, t2, h2; \
|
RLDICL $0, t2, $62, h2; \
|
||||||
AND t2, t4, t0; \
|
AND t2, t4, h0; \
|
||||||
ADDC t0, h0, h0; \
|
ADDC t0, h0, h0; \
|
||||||
ADDE t3, h1, h1; \
|
ADDE t3, t1, h1; \
|
||||||
SLD $62, t3, t4; \
|
SLD $62, t3, t4; \
|
||||||
SRD $2, t2; \
|
SRD $2, t2; \
|
||||||
ADDZE h2; \
|
ADDZE h2; \
|
||||||
@@ -75,6 +72,7 @@ TEXT ·update(SB), $0-32
|
|||||||
loop:
|
loop:
|
||||||
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
|
POLY1305_ADD(R4, R8, R9, R10, R20, R21, R22)
|
||||||
|
|
||||||
|
PCALIGN $16
|
||||||
multiply:
|
multiply:
|
||||||
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
|
POLY1305_MUL(R8, R9, R10, R11, R12, R16, R17, R18, R14, R20, R21)
|
||||||
ADD $-16, R5
|
ADD $-16, R5
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ func CommandContext(t testing.TB, ctx context.Context, name string, args ...stri
|
|||||||
// grace periods to clean up: one for the delay between the first
|
// grace periods to clean up: one for the delay between the first
|
||||||
// termination signal being sent (via the Cancel callback when the Context
|
// termination signal being sent (via the Cancel callback when the Context
|
||||||
// expires) and the process being forcibly terminated (via the WaitDelay
|
// expires) and the process being forcibly terminated (via the WaitDelay
|
||||||
// field), and a second one for the delay becween the process being
|
// field), and a second one for the delay between the process being
|
||||||
// terminated and and the test logging its output for debugging.
|
// terminated and the test logging its output for debugging.
|
||||||
//
|
//
|
||||||
// (We want to ensure that the test process itself has enough time to
|
// (We want to ensure that the test process itself has enough time to
|
||||||
// log the output before it is also terminated.)
|
// log the output before it is also terminated.)
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
|
// Package md4 implements the MD4 hash algorithm as defined in RFC 1320.
|
||||||
//
|
//
|
||||||
// Deprecated: MD4 is cryptographically broken and should should only be used
|
// Deprecated: MD4 is cryptographically broken and should only be used
|
||||||
// where compatibility with legacy systems, not security, is the goal. Instead,
|
// where compatibility with legacy systems, not security, is the goal. Instead,
|
||||||
// use a secure hash like SHA-256 (from crypto/sha256).
|
// use a secure hash like SHA-256 (from crypto/sha256).
|
||||||
package md4 // import "golang.org/x/crypto/md4"
|
package md4 // import "golang.org/x/crypto/md4"
|
||||||
|
|||||||
+7
-6
@@ -279,21 +279,22 @@ func getOIDFromHashAlgorithm(target crypto.Hash) asn1.ObjectIdentifier {
|
|||||||
|
|
||||||
// This is the exposed reflection of the internal OCSP structures.
|
// This is the exposed reflection of the internal OCSP structures.
|
||||||
|
|
||||||
// The status values that can be expressed in OCSP. See RFC 6960.
|
// The status values that can be expressed in OCSP. See RFC 6960.
|
||||||
|
// These are used for the Response.Status field.
|
||||||
const (
|
const (
|
||||||
// Good means that the certificate is valid.
|
// Good means that the certificate is valid.
|
||||||
Good = iota
|
Good = 0
|
||||||
// Revoked means that the certificate has been deliberately revoked.
|
// Revoked means that the certificate has been deliberately revoked.
|
||||||
Revoked
|
Revoked = 1
|
||||||
// Unknown means that the OCSP responder doesn't know about the certificate.
|
// Unknown means that the OCSP responder doesn't know about the certificate.
|
||||||
Unknown
|
Unknown = 2
|
||||||
// ServerFailed is unused and was never used (see
|
// ServerFailed is unused and was never used (see
|
||||||
// https://go-review.googlesource.com/#/c/18944). ParseResponse will
|
// https://go-review.googlesource.com/#/c/18944). ParseResponse will
|
||||||
// return a ResponseError when an error response is parsed.
|
// return a ResponseError when an error response is parsed.
|
||||||
ServerFailed
|
ServerFailed = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
// The enumerated reasons for revoking a certificate. See RFC 5280.
|
// The enumerated reasons for revoking a certificate. See RFC 5280.
|
||||||
const (
|
const (
|
||||||
Unspecified = 0
|
Unspecified = 0
|
||||||
KeyCompromise = 1
|
KeyCompromise = 1
|
||||||
|
|||||||
@@ -164,15 +164,23 @@ func testAgentInterface(t *testing.T, agent ExtendedAgent, key interface{}, cert
|
|||||||
data := []byte("hello")
|
data := []byte("hello")
|
||||||
sig, err := agent.Sign(pubKey, data)
|
sig, err := agent.Sign(pubKey, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
|
t.Logf("sign failed with key type %q", pubKey.Type())
|
||||||
}
|
// In integration tests ssh-dss and ssh-rsa (SHA1 signatures) may be
|
||||||
|
// disabled for security reasons, we check SHA-2 variants later.
|
||||||
if err := pubKey.Verify(data, sig); err != nil {
|
if pubKey.Type() != ssh.KeyAlgoDSA && pubKey.Type() != ssh.KeyAlgoRSA && pubKey.Type() != ssh.CertAlgoRSAv01 {
|
||||||
t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
|
t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := pubKey.Verify(data, sig); err != nil {
|
||||||
|
t.Logf("verify failed with key type %q", pubKey.Type())
|
||||||
|
if pubKey.Type() != ssh.KeyAlgoRSA {
|
||||||
|
t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For tests on RSA keys, try signing with SHA-256 and SHA-512 flags
|
// For tests on RSA keys, try signing with SHA-256 and SHA-512 flags
|
||||||
if pubKey.Type() == "ssh-rsa" {
|
if pubKey.Type() == ssh.KeyAlgoRSA {
|
||||||
sshFlagTest := func(flag SignatureFlags, expectedSigFormat string) {
|
sshFlagTest := func(flag SignatureFlags, expectedSigFormat string) {
|
||||||
sig, err = agent.SignWithFlags(pubKey, data, flag)
|
sig, err = agent.SignWithFlags(pubKey, data, flag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -185,7 +193,6 @@ func testAgentInterface(t *testing.T, agent ExtendedAgent, key interface{}, cert
|
|||||||
t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
|
t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sshFlagTest(0, ssh.KeyAlgoRSA)
|
|
||||||
sshFlagTest(SignatureFlagRsaSha256, ssh.KeyAlgoRSASHA256)
|
sshFlagTest(SignatureFlagRsaSha256, ssh.KeyAlgoRSASHA256)
|
||||||
sshFlagTest(SignatureFlagRsaSha512, ssh.KeyAlgoRSASHA512)
|
sshFlagTest(SignatureFlagRsaSha512, ssh.KeyAlgoRSASHA512)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -367,21 +367,21 @@ func TestCertTypes(t *testing.T) {
|
|||||||
|
|
||||||
func TestCertSignWithMultiAlgorithmSigner(t *testing.T) {
|
func TestCertSignWithMultiAlgorithmSigner(t *testing.T) {
|
||||||
type testcase struct {
|
type testcase struct {
|
||||||
sigAlgo string
|
sigAlgo string
|
||||||
algoritms []string
|
algorithms []string
|
||||||
}
|
}
|
||||||
cases := []testcase{
|
cases := []testcase{
|
||||||
{
|
{
|
||||||
sigAlgo: KeyAlgoRSA,
|
sigAlgo: KeyAlgoRSA,
|
||||||
algoritms: []string{KeyAlgoRSA, KeyAlgoRSASHA512},
|
algorithms: []string{KeyAlgoRSA, KeyAlgoRSASHA512},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sigAlgo: KeyAlgoRSASHA256,
|
sigAlgo: KeyAlgoRSASHA256,
|
||||||
algoritms: []string{KeyAlgoRSASHA256, KeyAlgoRSA, KeyAlgoRSASHA512},
|
algorithms: []string{KeyAlgoRSASHA256, KeyAlgoRSA, KeyAlgoRSASHA512},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sigAlgo: KeyAlgoRSASHA512,
|
sigAlgo: KeyAlgoRSASHA512,
|
||||||
algoritms: []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256},
|
algorithms: []string{KeyAlgoRSASHA512, KeyAlgoRSASHA256},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,7 +393,7 @@ func TestCertSignWithMultiAlgorithmSigner(t *testing.T) {
|
|||||||
|
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
t.Run(c.sigAlgo, func(t *testing.T) {
|
t.Run(c.sigAlgo, func(t *testing.T) {
|
||||||
signer, err := NewSignerWithAlgorithms(testSigners["rsa"].(AlgorithmSigner), c.algoritms)
|
signer, err := NewSignerWithAlgorithms(testSigners["rsa"].(AlgorithmSigner), c.algorithms)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("NewSignerWithAlgorithms error: %v", err)
|
t.Fatalf("NewSignerWithAlgorithms error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -384,7 +384,7 @@ func ExampleCertificate_SignCert() {
|
|||||||
}
|
}
|
||||||
mas, err := ssh.NewSignerWithAlgorithms(signer.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256})
|
mas, err := ssh.NewSignerWithAlgorithms(signer.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("unable to create signer with algoritms: ", err)
|
log.Fatal("unable to create signer with algorithms: ", err)
|
||||||
}
|
}
|
||||||
certificate := ssh.Certificate{
|
certificate := ssh.Certificate{
|
||||||
Key: publicKey,
|
Key: publicKey,
|
||||||
|
|||||||
+2
-2
@@ -610,7 +610,7 @@ func TestKnownHostsParsing(t *testing.T) {
|
|||||||
func TestFingerprintLegacyMD5(t *testing.T) {
|
func TestFingerprintLegacyMD5(t *testing.T) {
|
||||||
pub, _ := getTestKey()
|
pub, _ := getTestKey()
|
||||||
fingerprint := FingerprintLegacyMD5(pub)
|
fingerprint := FingerprintLegacyMD5(pub)
|
||||||
want := "fb:61:6d:1a:e3:f0:95:45:3c:a0:79:be:4a:93:63:66" // ssh-keygen -lf -E md5 rsa
|
want := "b7:ef:d3:d5:89:29:52:96:9f:df:47:41:4d:15:37:f4" // ssh-keygen -lf -E md5 rsa
|
||||||
if fingerprint != want {
|
if fingerprint != want {
|
||||||
t.Errorf("got fingerprint %q want %q", fingerprint, want)
|
t.Errorf("got fingerprint %q want %q", fingerprint, want)
|
||||||
}
|
}
|
||||||
@@ -619,7 +619,7 @@ func TestFingerprintLegacyMD5(t *testing.T) {
|
|||||||
func TestFingerprintSHA256(t *testing.T) {
|
func TestFingerprintSHA256(t *testing.T) {
|
||||||
pub, _ := getTestKey()
|
pub, _ := getTestKey()
|
||||||
fingerprint := FingerprintSHA256(pub)
|
fingerprint := FingerprintSHA256(pub)
|
||||||
want := "SHA256:Anr3LjZK8YVpjrxu79myrW9Hrb/wpcMNpVvTq/RcBm8" // ssh-keygen -lf rsa
|
want := "SHA256:fi5+D7UmDZDE9Q2sAVvvlpcQSIakN4DERdINgXd2AnE" // ssh-keygen -lf rsa
|
||||||
if fingerprint != want {
|
if fingerprint != want {
|
||||||
t.Errorf("got fingerprint %q want %q", fingerprint, want)
|
t.Errorf("got fingerprint %q want %q", fingerprint, want)
|
||||||
}
|
}
|
||||||
|
|||||||
+120
-50
@@ -426,6 +426,35 @@ func (l ServerAuthError) Error() string {
|
|||||||
return "[" + strings.Join(errs, ", ") + "]"
|
return "[" + strings.Join(errs, ", ") + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServerAuthCallbacks defines server-side authentication callbacks.
|
||||||
|
type ServerAuthCallbacks struct {
|
||||||
|
// PasswordCallback behaves like [ServerConfig.PasswordCallback].
|
||||||
|
PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
|
||||||
|
|
||||||
|
// PublicKeyCallback behaves like [ServerConfig.PublicKeyCallback].
|
||||||
|
PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
|
||||||
|
|
||||||
|
// KeyboardInteractiveCallback behaves like [ServerConfig.KeyboardInteractiveCallback].
|
||||||
|
KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
|
||||||
|
|
||||||
|
// GSSAPIWithMICConfig behaves like [ServerConfig.GSSAPIWithMICConfig].
|
||||||
|
GSSAPIWithMICConfig *GSSAPIWithMICConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// PartialSuccessError can be returned by any of the [ServerConfig]
|
||||||
|
// authentication callbacks to indicate to the client that authentication has
|
||||||
|
// partially succeeded, but further steps are required.
|
||||||
|
type PartialSuccessError struct {
|
||||||
|
// Next defines the authentication callbacks to apply to further steps. The
|
||||||
|
// available methods communicated to the client are based on the non-nil
|
||||||
|
// ServerAuthCallbacks fields.
|
||||||
|
Next ServerAuthCallbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PartialSuccessError) Error() string {
|
||||||
|
return "ssh: authenticated with partial success"
|
||||||
|
}
|
||||||
|
|
||||||
// ErrNoAuth is the error value returned if no
|
// ErrNoAuth is the error value returned if no
|
||||||
// authentication method has been passed yet. This happens as a normal
|
// authentication method has been passed yet. This happens as a normal
|
||||||
// part of the authentication loop, since the client first tries
|
// part of the authentication loop, since the client first tries
|
||||||
@@ -439,8 +468,18 @@ func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, err
|
|||||||
var perms *Permissions
|
var perms *Permissions
|
||||||
|
|
||||||
authFailures := 0
|
authFailures := 0
|
||||||
|
noneAuthCount := 0
|
||||||
var authErrs []error
|
var authErrs []error
|
||||||
var displayedBanner bool
|
var displayedBanner bool
|
||||||
|
partialSuccessReturned := false
|
||||||
|
// Set the initial authentication callbacks from the config. They can be
|
||||||
|
// changed if a PartialSuccessError is returned.
|
||||||
|
authConfig := ServerAuthCallbacks{
|
||||||
|
PasswordCallback: config.PasswordCallback,
|
||||||
|
PublicKeyCallback: config.PublicKeyCallback,
|
||||||
|
KeyboardInteractiveCallback: config.KeyboardInteractiveCallback,
|
||||||
|
GSSAPIWithMICConfig: config.GSSAPIWithMICConfig,
|
||||||
|
}
|
||||||
|
|
||||||
userAuthLoop:
|
userAuthLoop:
|
||||||
for {
|
for {
|
||||||
@@ -471,6 +510,11 @@ userAuthLoop:
|
|||||||
return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
|
return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.user != userAuthReq.User && partialSuccessReturned {
|
||||||
|
return nil, fmt.Errorf("ssh: client changed the user after a partial success authentication, previous user %q, current user %q",
|
||||||
|
s.user, userAuthReq.User)
|
||||||
|
}
|
||||||
|
|
||||||
s.user = userAuthReq.User
|
s.user = userAuthReq.User
|
||||||
|
|
||||||
if !displayedBanner && config.BannerCallback != nil {
|
if !displayedBanner && config.BannerCallback != nil {
|
||||||
@@ -491,20 +535,18 @@ userAuthLoop:
|
|||||||
|
|
||||||
switch userAuthReq.Method {
|
switch userAuthReq.Method {
|
||||||
case "none":
|
case "none":
|
||||||
if config.NoClientAuth {
|
noneAuthCount++
|
||||||
|
// We don't allow none authentication after a partial success
|
||||||
|
// response.
|
||||||
|
if config.NoClientAuth && !partialSuccessReturned {
|
||||||
if config.NoClientAuthCallback != nil {
|
if config.NoClientAuthCallback != nil {
|
||||||
perms, authErr = config.NoClientAuthCallback(s)
|
perms, authErr = config.NoClientAuthCallback(s)
|
||||||
} else {
|
} else {
|
||||||
authErr = nil
|
authErr = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow initial attempt of 'none' without penalty
|
|
||||||
if authFailures == 0 {
|
|
||||||
authFailures--
|
|
||||||
}
|
|
||||||
case "password":
|
case "password":
|
||||||
if config.PasswordCallback == nil {
|
if authConfig.PasswordCallback == nil {
|
||||||
authErr = errors.New("ssh: password auth not configured")
|
authErr = errors.New("ssh: password auth not configured")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -518,17 +560,17 @@ userAuthLoop:
|
|||||||
return nil, parseError(msgUserAuthRequest)
|
return nil, parseError(msgUserAuthRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
perms, authErr = config.PasswordCallback(s, password)
|
perms, authErr = authConfig.PasswordCallback(s, password)
|
||||||
case "keyboard-interactive":
|
case "keyboard-interactive":
|
||||||
if config.KeyboardInteractiveCallback == nil {
|
if authConfig.KeyboardInteractiveCallback == nil {
|
||||||
authErr = errors.New("ssh: keyboard-interactive auth not configured")
|
authErr = errors.New("ssh: keyboard-interactive auth not configured")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
prompter := &sshClientKeyboardInteractive{s}
|
prompter := &sshClientKeyboardInteractive{s}
|
||||||
perms, authErr = config.KeyboardInteractiveCallback(s, prompter.Challenge)
|
perms, authErr = authConfig.KeyboardInteractiveCallback(s, prompter.Challenge)
|
||||||
case "publickey":
|
case "publickey":
|
||||||
if config.PublicKeyCallback == nil {
|
if authConfig.PublicKeyCallback == nil {
|
||||||
authErr = errors.New("ssh: publickey auth not configured")
|
authErr = errors.New("ssh: publickey auth not configured")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -562,11 +604,18 @@ userAuthLoop:
|
|||||||
if !ok {
|
if !ok {
|
||||||
candidate.user = s.user
|
candidate.user = s.user
|
||||||
candidate.pubKeyData = pubKeyData
|
candidate.pubKeyData = pubKeyData
|
||||||
candidate.perms, candidate.result = config.PublicKeyCallback(s, pubKey)
|
candidate.perms, candidate.result = authConfig.PublicKeyCallback(s, pubKey)
|
||||||
if candidate.result == nil && candidate.perms != nil && candidate.perms.CriticalOptions != nil && candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
|
_, isPartialSuccessError := candidate.result.(*PartialSuccessError)
|
||||||
candidate.result = checkSourceAddress(
|
|
||||||
|
if (candidate.result == nil || isPartialSuccessError) &&
|
||||||
|
candidate.perms != nil &&
|
||||||
|
candidate.perms.CriticalOptions != nil &&
|
||||||
|
candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
|
||||||
|
if err := checkSourceAddress(
|
||||||
s.RemoteAddr(),
|
s.RemoteAddr(),
|
||||||
candidate.perms.CriticalOptions[sourceAddressCriticalOption])
|
candidate.perms.CriticalOptions[sourceAddressCriticalOption]); err != nil {
|
||||||
|
candidate.result = err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cache.add(candidate)
|
cache.add(candidate)
|
||||||
}
|
}
|
||||||
@@ -578,8 +627,8 @@ userAuthLoop:
|
|||||||
if len(payload) > 0 {
|
if len(payload) > 0 {
|
||||||
return nil, parseError(msgUserAuthRequest)
|
return nil, parseError(msgUserAuthRequest)
|
||||||
}
|
}
|
||||||
|
_, isPartialSuccessError := candidate.result.(*PartialSuccessError)
|
||||||
if candidate.result == nil {
|
if candidate.result == nil || isPartialSuccessError {
|
||||||
okMsg := userAuthPubKeyOkMsg{
|
okMsg := userAuthPubKeyOkMsg{
|
||||||
Algo: algo,
|
Algo: algo,
|
||||||
PubKey: pubKeyData,
|
PubKey: pubKeyData,
|
||||||
@@ -629,11 +678,11 @@ userAuthLoop:
|
|||||||
perms = candidate.perms
|
perms = candidate.perms
|
||||||
}
|
}
|
||||||
case "gssapi-with-mic":
|
case "gssapi-with-mic":
|
||||||
if config.GSSAPIWithMICConfig == nil {
|
if authConfig.GSSAPIWithMICConfig == nil {
|
||||||
authErr = errors.New("ssh: gssapi-with-mic auth not configured")
|
authErr = errors.New("ssh: gssapi-with-mic auth not configured")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
gssapiConfig := config.GSSAPIWithMICConfig
|
gssapiConfig := authConfig.GSSAPIWithMICConfig
|
||||||
userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload)
|
userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, parseError(msgUserAuthRequest)
|
return nil, parseError(msgUserAuthRequest)
|
||||||
@@ -689,49 +738,70 @@ userAuthLoop:
|
|||||||
break userAuthLoop
|
break userAuthLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
authFailures++
|
var failureMsg userAuthFailureMsg
|
||||||
if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries {
|
|
||||||
// If we have hit the max attempts, don't bother sending the
|
if partialSuccess, ok := authErr.(*PartialSuccessError); ok {
|
||||||
// final SSH_MSG_USERAUTH_FAILURE message, since there are
|
// After a partial success error we don't allow changing the user
|
||||||
// no more authentication methods which can be attempted,
|
// name and execute the NoClientAuthCallback.
|
||||||
// and this message may cause the client to re-attempt
|
partialSuccessReturned = true
|
||||||
// authentication while we send the disconnect message.
|
|
||||||
// Continue, and trigger the disconnect at the start of
|
// In case a partial success is returned, the server may send
|
||||||
// the loop.
|
// a new set of authentication methods.
|
||||||
//
|
authConfig = partialSuccess.Next
|
||||||
// The SSH specification is somewhat confusing about this,
|
|
||||||
// RFC 4252 Section 5.1 requires each authentication failure
|
// Reset pubkey cache, as the new PublicKeyCallback might
|
||||||
// be responded to with a respective SSH_MSG_USERAUTH_FAILURE
|
// accept a different set of public keys.
|
||||||
// message, but Section 4 says the server should disconnect
|
cache = pubKeyCache{}
|
||||||
// after some number of attempts, but it isn't explicit which
|
|
||||||
// message should take precedence (i.e. should there be a failure
|
// Send back a partial success message to the user.
|
||||||
// message than a disconnect message, or if we are going to
|
failureMsg.PartialSuccess = true
|
||||||
// disconnect, should we only send that message.)
|
} else {
|
||||||
//
|
// Allow initial attempt of 'none' without penalty.
|
||||||
// Either way, OpenSSH disconnects immediately after the last
|
if authFailures > 0 || userAuthReq.Method != "none" || noneAuthCount != 1 {
|
||||||
// failed authnetication attempt, and given they are typically
|
authFailures++
|
||||||
// considered the golden implementation it seems reasonable
|
}
|
||||||
// to match that behavior.
|
if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries {
|
||||||
continue
|
// If we have hit the max attempts, don't bother sending the
|
||||||
|
// final SSH_MSG_USERAUTH_FAILURE message, since there are
|
||||||
|
// no more authentication methods which can be attempted,
|
||||||
|
// and this message may cause the client to re-attempt
|
||||||
|
// authentication while we send the disconnect message.
|
||||||
|
// Continue, and trigger the disconnect at the start of
|
||||||
|
// the loop.
|
||||||
|
//
|
||||||
|
// The SSH specification is somewhat confusing about this,
|
||||||
|
// RFC 4252 Section 5.1 requires each authentication failure
|
||||||
|
// be responded to with a respective SSH_MSG_USERAUTH_FAILURE
|
||||||
|
// message, but Section 4 says the server should disconnect
|
||||||
|
// after some number of attempts, but it isn't explicit which
|
||||||
|
// message should take precedence (i.e. should there be a failure
|
||||||
|
// message than a disconnect message, or if we are going to
|
||||||
|
// disconnect, should we only send that message.)
|
||||||
|
//
|
||||||
|
// Either way, OpenSSH disconnects immediately after the last
|
||||||
|
// failed authentication attempt, and given they are typically
|
||||||
|
// considered the golden implementation it seems reasonable
|
||||||
|
// to match that behavior.
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var failureMsg userAuthFailureMsg
|
if authConfig.PasswordCallback != nil {
|
||||||
if config.PasswordCallback != nil {
|
|
||||||
failureMsg.Methods = append(failureMsg.Methods, "password")
|
failureMsg.Methods = append(failureMsg.Methods, "password")
|
||||||
}
|
}
|
||||||
if config.PublicKeyCallback != nil {
|
if authConfig.PublicKeyCallback != nil {
|
||||||
failureMsg.Methods = append(failureMsg.Methods, "publickey")
|
failureMsg.Methods = append(failureMsg.Methods, "publickey")
|
||||||
}
|
}
|
||||||
if config.KeyboardInteractiveCallback != nil {
|
if authConfig.KeyboardInteractiveCallback != nil {
|
||||||
failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
|
failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
|
||||||
}
|
}
|
||||||
if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil &&
|
if authConfig.GSSAPIWithMICConfig != nil && authConfig.GSSAPIWithMICConfig.Server != nil &&
|
||||||
config.GSSAPIWithMICConfig.AllowLogin != nil {
|
authConfig.GSSAPIWithMICConfig.AllowLogin != nil {
|
||||||
failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic")
|
failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(failureMsg.Methods) == 0 {
|
if len(failureMsg.Methods) == 0 {
|
||||||
return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
|
return nil, errors.New("ssh: no authentication methods available")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
|
if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,412 @@
|
|||||||
|
// Copyright 2024 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.
|
||||||
|
|
||||||
|
package ssh
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func doClientServerAuth(t *testing.T, serverConfig *ServerConfig, clientConfig *ClientConfig) ([]error, error) {
|
||||||
|
c1, c2, err := netPipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("netPipe: %v", err)
|
||||||
|
}
|
||||||
|
defer c1.Close()
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
var serverAuthErrors []error
|
||||||
|
|
||||||
|
serverConfig.AddHostKey(testSigners["rsa"])
|
||||||
|
serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) {
|
||||||
|
serverAuthErrors = append(serverAuthErrors, err)
|
||||||
|
}
|
||||||
|
go newServer(c1, serverConfig)
|
||||||
|
c, _, _, err := NewClientConn(c2, "", clientConfig)
|
||||||
|
if err == nil {
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
return serverAuthErrors, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiStepAuth(t *testing.T) {
|
||||||
|
// This user can login with password, public key or public key + password.
|
||||||
|
username := "testuser"
|
||||||
|
// This user can login with public key + password only.
|
||||||
|
usernameSecondFactor := "testuser_second_factor"
|
||||||
|
errPwdAuthFailed := errors.New("password auth failed")
|
||||||
|
errWrongSequence := errors.New("wrong sequence")
|
||||||
|
|
||||||
|
serverConfig := &ServerConfig{
|
||||||
|
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||||
|
if conn.User() == usernameSecondFactor {
|
||||||
|
return nil, errWrongSequence
|
||||||
|
}
|
||||||
|
if conn.User() == username && string(password) == clientPassword {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, errPwdAuthFailed
|
||||||
|
},
|
||||||
|
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
|
||||||
|
if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
|
||||||
|
if conn.User() == usernameSecondFactor {
|
||||||
|
return nil, &PartialSuccessError{
|
||||||
|
Next: ServerAuthCallbacks{
|
||||||
|
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||||
|
if string(password) == clientPassword {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, errPwdAuthFailed
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig := &ClientConfig{
|
||||||
|
User: usernameSecondFactor,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
Password(clientPassword),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err := doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("client login error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The error sequence is:
|
||||||
|
// - no auth passed yet
|
||||||
|
// - partial success
|
||||||
|
// - nil
|
||||||
|
if len(serverAuthErrors) != 3 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatalf("expected partial success error, got: %v", serverAuthErrors[1])
|
||||||
|
}
|
||||||
|
// Now test a wrong sequence.
|
||||||
|
clientConfig.Auth = []AuthMethod{
|
||||||
|
Password(clientPassword),
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("client login with wrong sequence must fail")
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - no auth passed yet
|
||||||
|
// - wrong sequence
|
||||||
|
// - partial success
|
||||||
|
if len(serverAuthErrors) != 3 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if serverAuthErrors[1] != errWrongSequence {
|
||||||
|
t.Fatal("server not returned wrong sequence")
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[2].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatalf("expected partial success error, got: %v", serverAuthErrors[2])
|
||||||
|
}
|
||||||
|
// Now test using a correct sequence but a wrong password before the right
|
||||||
|
// one.
|
||||||
|
n := 0
|
||||||
|
passwords := []string{"WRONG", "WRONG", clientPassword}
|
||||||
|
clientConfig.Auth = []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
RetryableAuthMethod(PasswordCallback(func() (string, error) {
|
||||||
|
p := passwords[n]
|
||||||
|
n++
|
||||||
|
return p, nil
|
||||||
|
}), 3),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("client login error: %s", err)
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - no auth passed yet
|
||||||
|
// - partial success
|
||||||
|
// - wrong password
|
||||||
|
// - wrong password
|
||||||
|
// - nil
|
||||||
|
if len(serverAuthErrors) != 5 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
if serverAuthErrors[2] != errPwdAuthFailed {
|
||||||
|
t.Fatal("server not returned password authentication failed")
|
||||||
|
}
|
||||||
|
if serverAuthErrors[3] != errPwdAuthFailed {
|
||||||
|
t.Fatal("server not returned password authentication failed")
|
||||||
|
}
|
||||||
|
// Only password authentication should fail.
|
||||||
|
clientConfig.Auth = []AuthMethod{
|
||||||
|
Password(clientPassword),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("client login with password only must fail")
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - no auth passed yet
|
||||||
|
// - wrong sequence
|
||||||
|
if len(serverAuthErrors) != 2 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if serverAuthErrors[1] != errWrongSequence {
|
||||||
|
t.Fatal("server not returned wrong sequence")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only public key authentication should fail.
|
||||||
|
clientConfig.Auth = []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("client login with public key only must fail")
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - no auth passed yet
|
||||||
|
// - partial success
|
||||||
|
if len(serverAuthErrors) != 2 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public key and wrong password.
|
||||||
|
clientConfig.Auth = []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
Password("WRONG"),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("client login with wrong password after public key must fail")
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - no auth passed yet
|
||||||
|
// - partial success
|
||||||
|
// - password auth failed
|
||||||
|
if len(serverAuthErrors) != 3 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
if serverAuthErrors[2] != errPwdAuthFailed {
|
||||||
|
t.Fatal("server not returned password authentication failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public key, public key again and then correct password. Public key
|
||||||
|
// authentication is attempted only once because the partial success error
|
||||||
|
// returns only "password" as the allowed authentication method.
|
||||||
|
clientConfig.Auth = []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
Password(clientPassword),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("client login error: %s", err)
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - no auth passed yet
|
||||||
|
// - partial success
|
||||||
|
// - nil
|
||||||
|
if len(serverAuthErrors) != 3 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[1].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The unrestricted username can do anything
|
||||||
|
clientConfig = &ClientConfig{
|
||||||
|
User: username,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
Password(clientPassword),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unrestricted client login error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig = &ClientConfig{
|
||||||
|
User: username,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unrestricted client login error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig = &ClientConfig{
|
||||||
|
User: username,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
Password(clientPassword),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unrestricted client login error: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDynamicAuthCallbacks(t *testing.T) {
|
||||||
|
user1 := "user1"
|
||||||
|
user2 := "user2"
|
||||||
|
errInvalidCredentials := errors.New("invalid credentials")
|
||||||
|
|
||||||
|
serverConfig := &ServerConfig{
|
||||||
|
NoClientAuth: true,
|
||||||
|
NoClientAuthCallback: func(conn ConnMetadata) (*Permissions, error) {
|
||||||
|
switch conn.User() {
|
||||||
|
case user1:
|
||||||
|
return nil, &PartialSuccessError{
|
||||||
|
Next: ServerAuthCallbacks{
|
||||||
|
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||||
|
if conn.User() == user1 && string(password) == clientPassword {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, errInvalidCredentials
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
case user2:
|
||||||
|
return nil, &PartialSuccessError{
|
||||||
|
Next: ServerAuthCallbacks{
|
||||||
|
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
|
||||||
|
if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
|
||||||
|
if conn.User() == user2 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, errInvalidCredentials
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, errInvalidCredentials
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig := &ClientConfig{
|
||||||
|
User: user1,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
Password(clientPassword),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err := doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("client login error: %s", err)
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - partial success
|
||||||
|
// - nil
|
||||||
|
if len(serverAuthErrors) != 2 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig = &ClientConfig{
|
||||||
|
User: user2,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("client login error: %s", err)
|
||||||
|
}
|
||||||
|
// The error sequence is:
|
||||||
|
// - partial success
|
||||||
|
// - nil
|
||||||
|
if len(serverAuthErrors) != 2 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
|
||||||
|
// user1 cannot login with public key
|
||||||
|
clientConfig = &ClientConfig{
|
||||||
|
User: user1,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
PublicKeys(testSigners["rsa"]),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("user1 login with public key must fail")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "no supported methods remain") {
|
||||||
|
t.Errorf("got %v, expected 'no supported methods remain'", err)
|
||||||
|
}
|
||||||
|
if len(serverAuthErrors) != 1 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
// user2 cannot login with password
|
||||||
|
clientConfig = &ClientConfig{
|
||||||
|
User: user2,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
Password(clientPassword),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err = doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("user2 login with password must fail")
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "no supported methods remain") {
|
||||||
|
t.Errorf("got %v, expected 'no supported methods remain'", err)
|
||||||
|
}
|
||||||
|
if len(serverAuthErrors) != 1 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if _, ok := serverAuthErrors[0].(*PartialSuccessError); !ok {
|
||||||
|
t.Fatal("server not returned partial success")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,8 +5,10 @@
|
|||||||
package ssh
|
package ssh
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -62,6 +64,133 @@ func TestClientAuthRestrictedPublicKeyAlgos(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMaxAuthTriesNoneMethod(t *testing.T) {
|
||||||
|
username := "testuser"
|
||||||
|
serverConfig := &ServerConfig{
|
||||||
|
MaxAuthTries: 2,
|
||||||
|
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||||
|
if conn.User() == username && string(password) == clientPassword {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid credentials")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c1, c2, err := netPipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("netPipe: %v", err)
|
||||||
|
}
|
||||||
|
defer c1.Close()
|
||||||
|
defer c2.Close()
|
||||||
|
|
||||||
|
var serverAuthErrors []error
|
||||||
|
|
||||||
|
serverConfig.AddHostKey(testSigners["rsa"])
|
||||||
|
serverConfig.AuthLogCallback = func(conn ConnMetadata, method string, err error) {
|
||||||
|
serverAuthErrors = append(serverAuthErrors, err)
|
||||||
|
}
|
||||||
|
go newServer(c1, serverConfig)
|
||||||
|
|
||||||
|
clientConfig := ClientConfig{
|
||||||
|
User: username,
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
clientConfig.SetDefaults()
|
||||||
|
// Our client will send 'none' auth only once, so we need to send the
|
||||||
|
// requests manually.
|
||||||
|
c := &connection{
|
||||||
|
sshConn: sshConn{
|
||||||
|
conn: c2,
|
||||||
|
user: username,
|
||||||
|
clientVersion: []byte(packageVersion),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.serverVersion, err = exchangeVersions(c.sshConn.conn, c.clientVersion)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to exchange version: %v", err)
|
||||||
|
}
|
||||||
|
c.transport = newClientTransport(
|
||||||
|
newTransport(c.sshConn.conn, clientConfig.Rand, true /* is client */),
|
||||||
|
c.clientVersion, c.serverVersion, &clientConfig, "", c.sshConn.RemoteAddr())
|
||||||
|
if err := c.transport.waitSession(); err != nil {
|
||||||
|
t.Fatalf("unable to wait session: %v", err)
|
||||||
|
}
|
||||||
|
c.sessionID = c.transport.getSessionID()
|
||||||
|
if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
|
||||||
|
t.Fatalf("unable to send ssh-userauth message: %v", err)
|
||||||
|
}
|
||||||
|
packet, err := c.transport.readPacket()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(packet) > 0 && packet[0] == msgExtInfo {
|
||||||
|
packet, err = c.transport.readPacket()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var serviceAccept serviceAcceptMsg
|
||||||
|
if err := Unmarshal(packet, &serviceAccept); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i := 0; i <= serverConfig.MaxAuthTries; i++ {
|
||||||
|
auth := new(noneAuth)
|
||||||
|
_, _, err := auth.auth(c.sessionID, clientConfig.User, c.transport, clientConfig.Rand, nil)
|
||||||
|
if i < serverConfig.MaxAuthTries {
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("client: got no error")
|
||||||
|
} else if !strings.Contains(err.Error(), "too many authentication failures") {
|
||||||
|
t.Fatalf("client: got unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(serverAuthErrors) != 3 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
for _, err := range serverAuthErrors {
|
||||||
|
if !errors.Is(err, ErrNoAuth) {
|
||||||
|
t.Errorf("go error: %v; want: %v", err, ErrNoAuth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMaxAuthTriesFirstNoneAuthErrorIgnored(t *testing.T) {
|
||||||
|
username := "testuser"
|
||||||
|
serverConfig := &ServerConfig{
|
||||||
|
MaxAuthTries: 1,
|
||||||
|
PasswordCallback: func(conn ConnMetadata, password []byte) (*Permissions, error) {
|
||||||
|
if conn.User() == username && string(password) == clientPassword {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("invalid credentials")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
clientConfig := &ClientConfig{
|
||||||
|
User: username,
|
||||||
|
Auth: []AuthMethod{
|
||||||
|
Password(clientPassword),
|
||||||
|
},
|
||||||
|
HostKeyCallback: InsecureIgnoreHostKey(),
|
||||||
|
}
|
||||||
|
|
||||||
|
serverAuthErrors, err := doClientServerAuth(t, serverConfig, clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("client login error: %s", err)
|
||||||
|
}
|
||||||
|
if len(serverAuthErrors) != 2 {
|
||||||
|
t.Fatalf("unexpected number of server auth errors: %v, errors: %+v", len(serverAuthErrors), serverAuthErrors)
|
||||||
|
}
|
||||||
|
if !errors.Is(serverAuthErrors[0], ErrNoAuth) {
|
||||||
|
t.Errorf("go error: %v; want: %v", serverAuthErrors[0], ErrNoAuth)
|
||||||
|
}
|
||||||
|
if serverAuthErrors[1] != nil {
|
||||||
|
t.Errorf("unexpected error: %v", serverAuthErrors[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewServerConnValidationErrors(t *testing.T) {
|
func TestNewServerConnValidationErrors(t *testing.T) {
|
||||||
serverConf := &ServerConfig{
|
serverConf := &ServerConfig{
|
||||||
PublicKeyAuthAlgorithms: []string{CertAlgoRSAv01},
|
PublicKeyAuthAlgorithms: []string{CertAlgoRSAv01},
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func TestAgentForward(t *testing.T) {
|
|||||||
|
|
||||||
sess, err := conn.NewSession()
|
sess, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("NewSession: %v", err)
|
t.Fatalf("NewSession: %v", err)
|
||||||
}
|
}
|
||||||
if err := agent.RequestAgentForwarding(sess); err != nil {
|
if err := agent.RequestAgentForwarding(sess); err != nil {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func TestCertLogin(t *testing.T) {
|
|||||||
s := newServer(t)
|
s := newServer(t)
|
||||||
|
|
||||||
// Use a key different from the default.
|
// Use a key different from the default.
|
||||||
clientKey := testSigners["dsa"]
|
clientKey := testSigners["ed25519"]
|
||||||
caAuthKey := testSigners["ecdsa"]
|
caAuthKey := testSigners["ecdsa"]
|
||||||
cert := &ssh.Certificate{
|
cert := &ssh.Certificate{
|
||||||
Key: clientKey.PublicKey(),
|
Key: clientKey.PublicKey(),
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ func testDial(t *testing.T, n, listenAddr string, x dialTester) {
|
|||||||
// on the opened connection.
|
// on the opened connection.
|
||||||
cancel()
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("Dial: %v", err)
|
t.Fatalf("Dial: %v", err)
|
||||||
}
|
}
|
||||||
x.TestClientConn(t, conn)
|
x.TestClientConn(t, conn)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -27,6 +28,9 @@ func testPortForward(t *testing.T, n, listenAddr string) {
|
|||||||
|
|
||||||
sshListener, err := conn.Listen(n, listenAddr)
|
sshListener, err := conn.Listen(n, listenAddr)
|
||||||
if err != nil {
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,6 +126,9 @@ func testAcceptClose(t *testing.T, n, listenAddr string) {
|
|||||||
|
|
||||||
sshListener, err := conn.Listen(n, listenAddr)
|
sshListener, err := conn.Listen(n, listenAddr)
|
||||||
if err != nil {
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +170,9 @@ func testPortForwardConnectionClose(t *testing.T, n, listenAddr string) {
|
|||||||
|
|
||||||
sshListener, err := client.Listen(n, listenAddr)
|
sshListener, err := client.Listen(n, listenAddr)
|
||||||
if err != nil {
|
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)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ import (
|
|||||||
"golang.org/x/crypto/ssh"
|
"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) {
|
func TestRunCommandSuccess(t *testing.T) {
|
||||||
server := newServer(t)
|
server := newServer(t)
|
||||||
conn := server.Dial(clientConfig())
|
conn := server.Dial(clientConfig())
|
||||||
@@ -29,6 +36,7 @@ func TestRunCommandSuccess(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("session failed: %v", err)
|
t.Fatalf("session failed: %v", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
@@ -66,6 +74,7 @@ func TestRunCommandStdin(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("session failed: %v", err)
|
t.Fatalf("session failed: %v", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
@@ -88,6 +97,7 @@ func TestRunCommandStdinError(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("session failed: %v", err)
|
t.Fatalf("session failed: %v", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
@@ -111,6 +121,7 @@ func TestRunCommandFailed(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("session failed: %v", err)
|
t.Fatalf("session failed: %v", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
@@ -127,6 +138,7 @@ func TestRunCommandWeClosed(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("session failed: %v", err)
|
t.Fatalf("session failed: %v", err)
|
||||||
}
|
}
|
||||||
err = session.Shell()
|
err = session.Shell()
|
||||||
@@ -146,6 +158,7 @@ func TestFuncLargeRead(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("unable to create new session: %s", 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++ {
|
for i := 0; i < 4; i++ {
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("unable to create new session: %s", err)
|
t.Fatalf("unable to create new session: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +237,7 @@ func TestValidTerminalMode(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("session failed: %v", err)
|
t.Fatalf("session failed: %v", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
@@ -287,6 +302,7 @@ func TestWindowChange(t *testing.T) {
|
|||||||
|
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("session failed: %v", err)
|
t.Fatalf("session failed: %v", err)
|
||||||
}
|
}
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
@@ -341,14 +357,10 @@ func testOneCipher(t *testing.T, cipher string, cipherOrder []string) {
|
|||||||
|
|
||||||
numBytes := 4096
|
numBytes := 4096
|
||||||
|
|
||||||
// Exercise sending data to the server
|
|
||||||
if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil {
|
|
||||||
t.Fatalf("SendRequest: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exercise receiving data from the server
|
// Exercise receiving data from the server
|
||||||
session, err := conn.NewSession()
|
session, err := conn.NewSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
skipIfIssue64959(t, err)
|
||||||
t.Fatalf("NewSession: %v", err)
|
t.Fatalf("NewSession: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +372,11 @@ func testOneCipher(t *testing.T, cipher string, cipherOrder []string) {
|
|||||||
if len(out) != numBytes {
|
if len(out) != numBytes {
|
||||||
t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes)
|
t.Fatalf("got %d bytes, want %d bytes", len(out), numBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exercise sending data to the server
|
||||||
|
if _, _, err := conn.Conn.SendRequest("drop-me", false, make([]byte, numBytes)); err != nil {
|
||||||
|
t.Fatalf("SendRequest: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var deprecatedCiphers = []string{
|
var deprecatedCiphers = []string{
|
||||||
@@ -431,7 +448,6 @@ func TestKeyExchanges(t *testing.T) {
|
|||||||
func TestClientAuthAlgorithms(t *testing.T) {
|
func TestClientAuthAlgorithms(t *testing.T) {
|
||||||
for _, key := range []string{
|
for _, key := range []string{
|
||||||
"rsa",
|
"rsa",
|
||||||
"dsa",
|
|
||||||
"ecdsa",
|
"ecdsa",
|
||||||
"ed25519",
|
"ed25519",
|
||||||
} {
|
} {
|
||||||
|
|||||||
@@ -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,
|
// addr is the user specified host:port. While we don't actually dial it,
|
||||||
// we need to know this for host key matching
|
// 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")
|
sshd, err := exec.LookPath("sshd")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.t.Skipf("skipping test: %v", err)
|
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 {
|
if err != nil {
|
||||||
s.t.Fatalf("unixConnection: %v", err)
|
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()
|
f, err := c2.File()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.t.Fatalf("UnixConn.File: %v", err)
|
s.t.Fatalf("UnixConn.File: %v", err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
cmd := testenv.Command(s.t, sshd, "-f", s.configfile, "-i", "-e")
|
||||||
cmd.Stdin = f
|
cmd.Stdin = f
|
||||||
cmd.Stdout = f
|
cmd.Stdout = f
|
||||||
cmd.Stderr = new(bytes.Buffer)
|
cmd.Stderr = new(bytes.Buffer)
|
||||||
@@ -223,7 +236,7 @@ func (s *server) TryDialWithAddr(config *ssh.ClientConfig, addr string) (*ssh.Cl
|
|||||||
// processes are killed too.
|
// processes are killed too.
|
||||||
cmd.Process.Signal(os.Interrupt)
|
cmd.Process.Signal(os.Interrupt)
|
||||||
cmd.Wait()
|
cmd.Wait()
|
||||||
if s.t.Failed() {
|
if s.t.Failed() || testing.Verbose() {
|
||||||
// log any output from sshd process
|
// log any output from sshd process
|
||||||
s.t.Logf("sshd:\n%s", cmd.Stderr)
|
s.t.Logf("sshd:\n%s", cmd.Stderr)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+29
-17
@@ -46,19 +46,31 @@ FFlRjzoB3Oxu8UQgb+MWPedtH9XYBbg9biz4jJLkXQ==
|
|||||||
-----END EC PRIVATE KEY-----
|
-----END EC PRIVATE KEY-----
|
||||||
`),
|
`),
|
||||||
"rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
|
"rsa": []byte(`-----BEGIN RSA PRIVATE KEY-----
|
||||||
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
|
||||||
-----END RSA PRIVATE KEY-----
|
-----END RSA PRIVATE KEY-----
|
||||||
`),
|
`),
|
||||||
"pkcs8": []byte(`-----BEGIN PRIVATE KEY-----
|
"pkcs8": []byte(`-----BEGIN PRIVATE KEY-----
|
||||||
@@ -190,17 +202,17 @@ var SSHCertificates = map[string][]byte{
|
|||||||
//
|
//
|
||||||
// 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub":
|
// 2. Assumes "ca" key above in file named "ca", sign a cert for "rsa.pub":
|
||||||
// ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub
|
// ssh-keygen -s ca -h -n host.example.com -V +500w -I host.example.com-key rsa.pub
|
||||||
"rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgLjYqmmuTSEmjVhSfLQphBSTJMLwIZhRgmpn8FHKLiEIAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABZHN8UAAAAAGsjIYUAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABDwAAAAdzc2gtcnNhAAABALeDea+60H6xJGhktAyosHaSY7AYzLocaqd8hJQjEIDifBwzoTlnBmcK9CxGhKuaoJFThdCLdaevCeOSuquh8HTkf+2ebZZc/G5T+2thPvPqmcuEcmMosWo+SIjYhbP3S6KD49aLC1X0kz8IBQeauFvURhkZ5ZjhA1L4aQYt9NjL73nqOl8PplRui+Ov5w8b4ldul4zOvYAFrzfcP6wnnXk3c1Zzwwf5wynD5jakO8GpYKBuhM7Z4crzkKSQjU3hla7xqgfomC5Gz4XbR2TNjcQiRrJQ0UlKtX3X3ObRCEhuvG0Kzjklhv+Ddw6txrhKjMjiSi/Yyius/AE8TmC1p4U= host.example.com
|
"rsa": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgWcP1x+t9PQTxkt/fRa8v5HXz0FFW/fwN3mpR5jdGo3UAAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAACAAAAFGhvc3QuZXhhbXBsZS5jb20ta2V5AAAAFAAAABBob3N0LmV4YW1wbGUuY29tAAAAAGXEzUQAAAAAd8sPtQAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEPAAAAB3NzaC1yc2EAAAEAs8/78EsftS/0+6CfUAtRhmgpOPZVH8XJc2o4Qx/lQCBg/uB2sucGGx/5BuFUwAjhMNQ1UejJ6+AbNgZNlH7LIssGxpcW+eKQXLfd9KwWNPCU3DqZGiMBsYESNtVLjKAMuvJmxKFFu4rceyya+GZfsQFJR7G++XK0cQQ4rgDSnQo3pxQnHwguFWeHtwjdOj0helYER4XDKjKQlo0SxI1nVo7n1jkl8QghdxX6HKia6MP7MqstgNujTvrCEUJ6L3YflD/SJ00Y3ySD9+5hqvfqrDh4c4rRuc4+k0e3fYZwyWO2NNtKHRBOZAgW8zzfR3G99YdTw8N8+2oXeAdvB9k0tA== host.example.com
|
||||||
`),
|
`),
|
||||||
"rsa-sha2-256": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgOyK28gunJkM60qp4EbsYAjgbUsyjS8u742OLjipIgc0AAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMJ4AAAAAHBPBLwAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi0yNTYAAAEAbG4De/+QiqopPS3O1H7ySeEUCY56qmdgr02sFErnihdXPDaWXUXxacvJHaEtLrSTSaPL/3v3iKvjLWDOHaQ5c+cN9J7Tqzso7RQCXZD2nK9bwCUyBoiDyBCRe8w4DQEtfL5okpVzQsSAiojQ8hBohMOpy3gFfXrdm4PVC1ZKqlZh4fAc7ajieRq/Tpq2xOLdHwxkcgPNR83WVHva6K9/xjev/5n227/gkHo0qbGs8YYDOFXIEhENi+B23IzxdNVieWdyQpYpe0C2i95Jhyo0wJmaFY2ArruTS+D1jGQQpMPvAQRy26/A5hI83GLhpwyhrN/M8wCxzAhyPL6Ieuh5tQ== host.example.com
|
"rsa-sha2-256": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg4+hKHVPKv183MU/Q7XD/mzDBFSc2YY3eraltxLMGJo0AAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAACAAAAFGhvc3QuZXhhbXBsZS5jb20ta2V5AAAAFAAAABBob3N0LmV4YW1wbGUuY29tAAAAAGXEzYAAAAAAd8sP4wAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEUAAAADHJzYS1zaGEyLTI1NgAAAQA/ByIegNZYJRRl413S/8LxGvTZnbxsPwaluoJ/54niGZV9P28THz7d9jXfSHPjalhH93jNPfTYXvI4opnDC37ua1Nu8KKfk40IWXnnDdZLWraUxEidIzhmfVtz8kGdGoFQ8H0EzubL7zKNOTlfSfOoDlmQVOuxT/+eh2mEp4ri0/+8J1mLfLBr8tREX0/iaNjK+RKdcyTMicKursAYMCDdu8vlaphxea+ocyHM9izSX/l33t44V13ueTqIOh2Zbl2UE2k+jk+0dc1CmV0SEoiWiIyt8TRM4yQry1vPlQLsrf28sYM/QMwnhCVhyZO3vs5F25aQWrB9d51VEzBW9/fd host.example.com
|
||||||
`),
|
`),
|
||||||
"rsa-sha2-512": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgFGv4IpXfs4L/Y0b3rmUdPFhWoUrVnXuPxXr6aHGs7wgAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAgAAABRob3N0LmV4YW1wbGUuY29tLWtleQAAABQAAAAQaG9zdC5leGFtcGxlLmNvbQAAAABeSMRYAAAAAHBPBp4AAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAnF4fVj6mm+UFeNCIf9AKJCv9WzymjjPvzzmaMWWkPWqoV0P0m5SiYfvbY9SbA73Blpv8SOr0DmpublF183kodREia4KyVuC8hLhSCV2Y16hy9MBegOZMepn80w+apj7Rn9QCz5OfEakDdztp6OWTBtqxnZFcTQ4XrgFkNWeWRElGdEvAVNn2WHwHi4EIdz0mdv48Imv5SPlOuW862ZdFG4Do1dUfDIiGsBofLlgcyIYlf+eNHul6sBeUkuwFxisMpI5DQzNp8PX1g/QJA2wzwT674PTqDXNttKjyh50Fdr4sXxm9Gz1+jVLoESvFNa55ERdSyAqNu4wTy11MZsWwSA== host.example.com
|
"rsa-sha2-512": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgylCoUX+0nYXGG9k/KEepcgEd22921eUwSQsYuQXKOswAAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAACAAAAFGhvc3QuZXhhbXBsZS5jb20ta2V5AAAAFAAAABBob3N0LmV4YW1wbGUuY29tAAAAAGXEzbwAAAAAd8sQBAAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEUAAAADHJzYS1zaGEyLTUxMgAAAQADOjYUNxzwYZ9O3zjjZSKhX7Ix/vUBq8lIltBRckbKJtcjn2/qqtaeZK2ijkbMlnPFCJ59U+Z6m4DMU6gxYF8R9/WJrANlWYNQ4+52fXjE/FPDdJkwB/kPWABt+ffEiM1HfzP4/zXgTtOJ0GogEzTYoMSrhAlpdKACUaC9nCQ7gjmO+owGkrB3ZbyQS4gltqQZjiBNqF0P/vxmXP+0Kx66/ei8JNYUpEPCXT4ZhLZmsVptaYD1gpvc2i5T5LnjRrsvf4Q6EKR+gwJEjlwnylhH5+h+ZU/KXydkw1hhEVP+ZiIBkVo9nN78Qb/VMJum4Fdoltuyh/9k2lMDeyDuRVh7 host.example.com
|
||||||
`),
|
`),
|
||||||
// Assumes "ca" key above in file named "ca", sign a user cert for "rsa.pub"
|
// Assumes "ca" key above in file named "ca", sign a user cert for "rsa.pub"
|
||||||
// using "testcertificate" as principal:
|
// using "testcertificate" as principal:
|
||||||
//
|
//
|
||||||
// ssh-keygen -s ca -I username -n testcertificate rsa.pub
|
// ssh-keygen -s ca -I username -n testcertificate rsa.pub
|
||||||
"rsa-user-testcertificate": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgr0MnhSf+KkQWEQmweJOGsJfOrUt80pQZDaI9YiwSfDUAAAADAQABAAAAgQC8A6FGHDiWCSREAXCq6yBfNVr0xCVG2CzvktFNRpue+RXrGs/2a6ySEJQb3IYquw7HlJgu6fg3WIWhOmHCjfpG0PrL4CRwbqQ2LaPPXhJErWYejcD8Di00cF3677+G10KMZk9RXbmHtuBFZT98wxg8j+ZsBMqGM1+7yrWUvynswQAAAAAAAAAAAAAAAQAAAAh1c2VybmFtZQAAABMAAAAPdGVzdGNlcnRpZmljYXRlAAAAAAAAAAD//////////wAAAAAAAACCAAAAFXBlcm1pdC1YMTEtZm9yd2FyZGluZwAAAAAAAAAXcGVybWl0LWFnZW50LWZvcndhcmRpbmcAAAAAAAAAFnBlcm1pdC1wb3J0LWZvcndhcmRpbmcAAAAAAAAACnBlcm1pdC1wdHkAAAAAAAAADnBlcm1pdC11c2VyLXJjAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQC+D11D0hEbn2Vglv4YRJ8pZNyHjIGmvth3DWOQrq++2vH2MujmGQDxfr4SVE9GpMBlKU3lwGbpgIBxAg6yZcNSfo6PWVU9ACg6NMFO+yMzc2MaG+/naQdNjSewywF5j2rkNO2XOaViRVSrZroe2B/aY2LTV0jDl8nu5NOjwRs1/s7SLe5z1rw/X0dpmXk0qJY3gQhmR8HZZ1dhEkJUGwaBCPd0T8asSYf1Ag2rUD4aQ28r3q69mbwfWOOa6rMemVZruUV5dzHwVNVNtVv+ImtnYtz8m8g+K0plaGptHn3KsaOnASkh3tujhaE7kvc4HR9Igli9+76jhZie3h/dTN5zAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAFuA+67KvnlmcodIp0Lv4mR9UW/CHghAaN1csBJTkI8mx3wXKyIPTsS2uXboEhWD0a7S9gps2SEwC5m6E3kV2Rzg7aH1S03GZqMvVlK2VHe7fzuoW2yOKk6yEPjeTF0pKCFbUQ6mce8pRpD/zdvjG0Z287XM3c3Axlrn7qq7TS0MDTjEZ/dsUNFHxep3co/HuAsWVWPVDItr/FPnvZ6WVH1yc8N/AJn0gLHobkGgug22vI9rNIge1wrnXxU9BUSouzkau/PQsrCQapnn+I1H7HaQt0wdk45nxMP+ags+HRI9qpX/p8WDn6+zpqYqN/nfw2aoytyaJqhsV32Teuqtrgg== rsa.pub
|
"rsa-user-testcertificate": []byte(`ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgEKR9xnhXkbi/pgP669VjBH6XVTYR0yx1wunCtOIjzjUAAAADAQABAAABAQCe6jMoy1xCQgiZkZJ7gi6NLj4uRqz2OaUGK/OJYZTfBqK+SlS9iymAluHu9K+cc4+0qxx0gn7dRTJWINSgzvca6ayYe995EKgD1hE5krh9BH0bRrXB+hGqyslcZOgLNO+v8jYojClQbRtET2tS+xb4k33GCuL5wgla2790ZgOQgs7huQUjG0S8c1W+EYt6fI4cWE/DeEBnv9sqryS8rOb0PbM6WUd7XBadwySFWYQUX0ei56GNt12Z4gADEGlFQV/OnV0PvnTcAMGUl0rfToPgJ4jgogWKoTVWuZ9wyA/x+2LRLRvgm2a969ig937/AH0i0Wq+FzqfK7EXQ99Yf5K/AAAAAAAAAAAAAAABAAAACHVzZXJuYW1lAAAAEwAAAA90ZXN0Y2VydGlmaWNhdGUAAAAAAAAAAP//////////AAAAAAAAAIIAAAAVcGVybWl0LVgxMS1mb3J3YXJkaW5nAAAAAAAAABdwZXJtaXQtYWdlbnQtZm9yd2FyZGluZwAAAAAAAAAWcGVybWl0LXBvcnQtZm9yd2FyZGluZwAAAAAAAAAKcGVybWl0LXB0eQAAAAAAAAAOcGVybWl0LXVzZXItcmMAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAL4PXUPSERufZWCW/hhEnylk3IeMgaa+2HcNY5Cur77a8fYy6OYZAPF+vhJUT0akwGUpTeXAZumAgHECDrJlw1J+jo9ZVT0AKDo0wU77IzNzYxob7+dpB02NJ7DLAXmPauQ07Zc5pWJFVKtmuh7YH9pjYtNXSMOXye7k06PBGzX+ztIt7nPWvD9fR2mZeTSoljeBCGZHwdlnV2ESQlQbBoEI93RPxqxJh/UCDatQPhpDbyverr2ZvB9Y45rqsx6ZVmu5RXl3MfBU1U21W/4ia2di3PybyD4rSmVoam0efcqxo6cBKSHe26OFoTuS9zgdH0iCWL37vqOFmJ7eH91M3nMAAAEUAAAADHJzYS1zaGEyLTUxMgAAAQCKVn2S7FJYhXTRVbcz1Di1HLz1g5Yae5WBhd0Tg471XkNw7ylcCK23Wnrzj1GxrW0oWCCGHROtUnxQXei1xNWt8HONN+eeafrJSZJR6ald3Yd4OveXlHNT6mEDPgqRj4B56OPoY33LzpaFlQZlZ6U9KXySshNaCTjVp3ojTj6uPNxcuOnG9O5emEPC2eaM4QYsz4cqHNJ9SWWEu+HIQgpx5SM12qcrq/KhN6WJhG3edL1YAsxkf1/THEcfi6wvsHi+DKewJ5hZ876//japjHBKA9SB7gsCrLx3m+0XI8TkWUZTZJHETJHHVjJN8xjRvMv5gWKLvRsz7ScmnN1+ckL6 rsa.pub
|
||||||
`),
|
`),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3078,34 +3078,6 @@ WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
|
|||||||
e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
|
e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
|
||||||
TpPDpFQUWw==
|
TpPDpFQUWw==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
# CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1,OU=Kamu Sertifikasyon Merkezi - Kamu SM,O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK,L=Gebze - Kocaeli,C=TR
|
|
||||||
# 46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
|
|
||||||
GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
|
|
||||||
bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
|
|
||||||
KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
|
|
||||||
BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
|
|
||||||
dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
|
|
||||||
EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
|
|
||||||
IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
|
|
||||||
QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
|
|
||||||
TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
|
|
||||||
LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
|
|
||||||
a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
|
|
||||||
LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
|
|
||||||
N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
|
|
||||||
YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
|
|
||||||
iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
|
|
||||||
AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
|
|
||||||
V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
|
|
||||||
BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
|
|
||||||
AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
|
|
||||||
IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
|
|
||||||
lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
|
|
||||||
8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
|
|
||||||
lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
# CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW
|
# CN=TWCA Global Root CA,OU=Root CA,O=TAIWAN-CA,C=TW
|
||||||
# 59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b
|
# 59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
@@ -3162,6 +3134,58 @@ lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
|
|||||||
aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
|
aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
|
||||||
YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
|
YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
|
||||||
-----END CERTIFICATE-----
|
-----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
|
# CN=Telia Root CA v2,O=Telia Finland Oyj,C=FI
|
||||||
# 242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c
|
# 242b69742fcb1e5b2abf98898b94572187544e5b4d9911786573621f6a74b82c
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
@@ -3740,28 +3764,6 @@ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
|
|||||||
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
|
dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
|
||||||
ReYNnyicsbkqWletNw+vHX/bvZ8=
|
ReYNnyicsbkqWletNw+vHX/bvZ8=
|
||||||
-----END CERTIFICATE-----
|
-----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
|
# OU=Security Communication RootCA2,O=SECOM Trust Systems CO.\,LTD.,C=JP
|
||||||
# 513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6
|
# 513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6
|
||||||
-----BEGIN CERTIFICATE-----
|
-----BEGIN CERTIFICATE-----
|
||||||
|
|||||||
@@ -147,6 +147,20 @@ func parseTrustClass(s *bufio.Scanner) ([sha1.Size]byte, *trustObj, error) {
|
|||||||
return h, to, nil
|
return h, to, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// manualExclusions contains a map of SHA1 fingerprints of roots that we manually exclude
|
||||||
|
// from the bundle for various reasons.
|
||||||
|
var manualExclusions = map[string]bool{
|
||||||
|
// TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
|
||||||
|
// We exclude this root because mozilla manually constrains this root to
|
||||||
|
// issue names under .tr, but this information is only encoded in the CCADB
|
||||||
|
// IncludedCACertificateReport, in a field the format of which is
|
||||||
|
// undocumented, and is only used for this particular certificate. Rather
|
||||||
|
// than adding special parsing for this, we skip it. When code constraint
|
||||||
|
// support is available, we may also want to simply add a manual constraint,
|
||||||
|
// rather than a manual exclusion.
|
||||||
|
"3143649becce27eced3a3f0b8f0de4e891ddeeca": true,
|
||||||
|
}
|
||||||
|
|
||||||
// Parse parses a NSS certdata.txt formatted file, returning only
|
// Parse parses a NSS certdata.txt formatted file, returning only
|
||||||
// trusted serverAuth roots, as well as any additional constraints. This parser
|
// trusted serverAuth roots, as well as any additional constraints. This parser
|
||||||
// is very opinionated, only returning roots that are currently trusted for
|
// is very opinionated, only returning roots that are currently trusted for
|
||||||
@@ -248,6 +262,9 @@ func Parse(r io.Reader) ([]*Certificate, error) {
|
|||||||
if !e.trust.trusted {
|
if !e.trust.trusted {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if manualExclusions[fmt.Sprintf("%x", h)] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
nssCert := &Certificate{X509: e.cert.c}
|
nssCert := &Certificate{X509: e.cert.c}
|
||||||
if e.cert.DistrustAfter != nil {
|
if e.cert.DistrustAfter != nil {
|
||||||
nssCert.Constraints = append(nssCert.Constraints, DistrustAfter(*e.cert.DistrustAfter))
|
nssCert.Constraints = append(nssCert.Constraints, DistrustAfter(*e.cert.DistrustAfter))
|
||||||
|
|||||||
Reference in New Issue
Block a user