[backport]fix CVE-2024-45341 CVE-2024-45336

This commit is contained in:
wujichao 2025-02-21 11:38:12 +08:00
parent 0e85a0bca2
commit d0130fc44f
4 changed files with 707 additions and 1 deletions

View File

@ -0,0 +1,92 @@
From 468fad45a27db0ec1fff4ae397d3670795b3f977 Mon Sep 17 00:00:00 2001
From: Roland Shoemaker <bracewell@google.com>
Date: Mon, 09 Dec 2024 11:31:22 -0800
Subject: [PATCH] [release-branch.go1.24] crypto/x509: properly check for IPv6 hosts in URIs
When checking URI constraints, use netip.ParseAddr, which understands
zones, unlike net.ParseIP which chokes on them. This prevents zone IDs
from mistakenly satisfying URI constraints.
Thanks to Juho Forsén of Mattermost for reporting this issue.
For #71156
Fixes #71209
Fixes CVE-2024-45341
Change-Id: Iecac2529f3605382d257996e0fb6d6983547e400
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1700
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit 22ca55d396ba801e6ae9b2bd67a059fcb30562fd)
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1800
Commit-Queue: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/643099
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
---
diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go
index 008c702..a585184 100644
--- a/src/crypto/x509/name_constraints_test.go
+++ b/src/crypto/x509/name_constraints_test.go
@@ -1607,6 +1607,23 @@
cn: "foo.bar",
},
},
+ // #86: URIs with IPv6 addresses with zones and ports are rejected
+ {
+ roots: []constraintsSpec{
+ {
+ ok: []string{"uri:example.com"},
+ },
+ },
+ intermediates: [][]constraintsSpec{
+ {
+ {},
+ },
+ },
+ leaf: leafSpec{
+ sans: []string{"uri:http://[2006:abcd::1%25.example.com]:16/"},
+ },
+ expectedError: "URI with IP",
+ },
}
func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) {
diff --git a/src/crypto/x509/verify.go b/src/crypto/x509/verify.go
index d2384f5..5fe93c6 100644
--- a/src/crypto/x509/verify.go
+++ b/src/crypto/x509/verify.go
@@ -15,6 +15,7 @@
"strings"
"time"
"unicode/utf8"
+ _ "unsafe"
)
type InvalidReason int
@@ -427,14 +428,20 @@
}
}
- if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") ||
- net.ParseIP(host) != nil {
+ // parseIPZone will reject the URI IPv6 literal form "[...]", so we
+ // check if _either_ the string parses as an IP, or if it is enclosed in
+ // square brackets.
+ ipaddr, _ := parseIPZone(host)
+ if ipaddr != nil || (strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]")) {
return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String())
}
return matchDomainConstraint(host, constraint)
}
+//go:linkname parseIPZone net.parseIPZone
+func parseIPZone(s string) (net.IP, string)
+
func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) {
if len(ip) != len(constraint.IP) {
return false, nil

View File

@ -0,0 +1,388 @@
From 6b605505047416bbbf513bba1540220a8897f3f6 Mon Sep 17 00:00:00 2001
From: Damien Neil <dneil@google.com>
Date: Fri, 22 Nov 2024 12:34:11 -0800
Subject: [PATCH] [release-branch.go1.24] net/http: persist header stripping across repeated redirects
When an HTTP redirect changes the host of a request, we drop
sensitive headers such as Authorization from the redirected request.
Fix a bug where a chain of redirects could result in sensitive
headers being sent to the wrong host:
1. request to a.tld with Authorization header
2. a.tld redirects to b.tld
3. request to b.tld with no Authorization header
4. b.tld redirects to b.tld
3. request to b.tld with Authorization header restored
Thanks to Kyle Seely for reporting this issue.
For #70530
Fixes #71212
Fixes CVE-2024-45336
Change-Id: Ia58a2e10d33d6b0cc7220935e771450e5c34de72
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1641
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
Commit-Queue: Roland Shoemaker <bracewell@google.com>
(cherry picked from commit 2889169b87a61f1218a02994feb80fd3d8bfa87c)
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/1766
Reviewed-on: https://go-review.googlesource.com/c/go/+/643100
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
---
diff --git a/src/net/http/client.go b/src/net/http/client.go
index fda7815..9231f63 100644
--- a/src/net/http/client.go
+++ b/src/net/http/client.go
@@ -615,8 +615,9 @@
reqBodyClosed = false // have we closed the current req.Body?
// Redirect behavior:
- redirectMethod string
- includeBody bool
+ redirectMethod string
+ includeBody = true
+ stripSensitiveHeaders = false
)
uerr := func(err error) error {
// the body may have been closed already by c.send()
@@ -681,7 +682,12 @@
// in case the user set Referer on their first request.
// If they really want to override, they can do it in
// their CheckRedirect func.
- copyHeaders(req)
+ if !stripSensitiveHeaders && reqs[0].URL.Host != req.URL.Host {
+ if !shouldCopyHeaderOnRedirect(reqs[0].URL, req.URL) {
+ stripSensitiveHeaders = true
+ }
+ }
+ copyHeaders(req, stripSensitiveHeaders)
// Add the Referer header from the most recent
// request URL to the new one, if it's not https->http:
@@ -747,7 +753,7 @@
// makeHeadersCopier makes a function that copies headers from the
// initial Request, ireq. For every redirect, this function must be called
// so that it can copy headers into the upcoming Request.
-func (c *Client) makeHeadersCopier(ireq *Request) func(*Request) {
+func (c *Client) makeHeadersCopier(ireq *Request) func(req *Request, stripSensitiveHeaders bool) {
// The headers to copy are from the very initial request.
// We use a closured callback to keep a reference to these original headers.
var (
@@ -761,8 +767,7 @@
}
}
- preq := ireq // The previous request
- return func(req *Request) {
+ return func(req *Request, stripSensitiveHeaders bool) {
// If Jar is present and there was some initial cookies provided
// via the request header, then we may need to alter the initial
// cookies as we follow redirects since each redirect may end up
@@ -799,12 +804,15 @@
// Copy the initial request's Header values
// (at least the safe ones).
for k, vv := range ireqhdr {
- if shouldCopyHeaderOnRedirect(k, preq.URL, req.URL) {
+ sensitive := false
+ switch CanonicalHeaderKey(k) {
+ case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
+ sensitive = true
+ }
+ if !(sensitive && stripSensitiveHeaders) {
req.Header[k] = vv
}
}
-
- preq = req // Update previous Request with the current request
}
}
@@ -984,28 +984,23 @@ func (b *cancelTimerBody) Close() error {
return err
}
-func shouldCopyHeaderOnRedirect(headerKey string, initial, dest *url.URL) bool {
- switch CanonicalHeaderKey(headerKey) {
- case "Authorization", "Www-Authenticate", "Cookie", "Cookie2":
- // Permit sending auth/cookie headers from "foo.com"
- // to "sub.foo.com".
-
- // Note that we don't send all cookies to subdomains
- // automatically. This function is only used for
- // Cookies set explicitly on the initial outgoing
- // client request. Cookies automatically added via the
- // CookieJar mechanism continue to follow each
- // cookie's scope as set by Set-Cookie. But for
- // outgoing requests with the Cookie header set
- // directly, we don't know their scope, so we assume
- // it's for *.domain.com.
-
- ihost := idnaASCIIFromURL(initial)
- dhost := idnaASCIIFromURL(dest)
- return isDomainOrSubdomain(dhost, ihost)
- }
- // All other headers are copied:
- return true
+func shouldCopyHeaderOnRedirect(initial, dest *url.URL) bool {
+ // Permit sending auth/cookie headers from "foo.com"
+ // to "sub.foo.com".
+
+ // Note that we don't send all cookies to subdomains
+ // automatically. This function is only used for
+ // Cookies set explicitly on the initial outgoing
+ // client request. Cookies automatically added via the
+ // CookieJar mechanism continue to follow each
+ // cookie's scope as set by Set-Cookie. But for
+ // outgoing requests with the Cookie header set
+ // directly, we don't know their scope, so we assume
+ // it's for *.domain.com.
+
+ ihost := idnaASCIIFromURL(initial)
+ dhost := idnaASCIIFromURL(dest)
+ return isDomainOrSubdomain(dhost, ihost)
}
// isDomainOrSubdomain reports whether sub is a subdomain (or exact
diff --git a/src/net/http/client_test.go b/src/net/http/client_test.go
index 429b8f1..1ce9539 100644
--- a/src/net/http/client_test.go
+++ b/src/net/http/client_test.go
@@ -1525,6 +1525,63 @@ func TestClientCopyHeadersOnRedirect(t *testing.T) {
}
}
+// Issue #70530: Once we strip a header on a redirect to a different host,
+// the header should stay stripped across any further redirects.
+func TestClientStripHeadersOnRepeatedRedirect_h1(t *testing.T) {
+ testClientStripHeadersOnRepeatedRedirect(t, h1Mode)
+}
+func TestClientStripHeadersOnRepeatedRedirect_h2(t *testing.T) {
+ testClientStripHeadersOnRepeatedRedirect(t, h2Mode)
+}
+func testClientStripHeadersOnRepeatedRedirect(t *testing.T, mode bool) {
+ setParallel(t)
+ defer afterTest(t)
+ var proto string
+ cst := newClientServerTest(t, mode, HandlerFunc(func(w ResponseWriter, r *Request) {
+ if r.Host+r.URL.Path != "a.example.com/" {
+ if h := r.Header.Get("Authorization"); h != "" {
+ t.Errorf("on request to %v%v, Authorization=%q, want no header", r.Host, r.URL.Path, h)
+ }
+ }
+ // Follow a chain of redirects from a to b and back to a.
+ // The Authorization header is stripped on the first redirect to b,
+ // and stays stripped even if we're sent back to a.
+ switch r.Host + r.URL.Path {
+ case "a.example.com/":
+ Redirect(w, r, proto+"://b.example.com/", StatusFound)
+ case "b.example.com/":
+ Redirect(w, r, proto+"://b.example.com/redirect", StatusFound)
+ case "b.example.com/redirect":
+ Redirect(w, r, proto+"://a.example.com/redirect", StatusFound)
+ case "a.example.com/redirect":
+ w.Header().Set("X-Done", "true")
+ default:
+ t.Errorf("unexpected request to %v", r.URL)
+ }
+ }))
+ defer cst.close()
+
+ ts := cst.ts
+ proto = strings.Split(ts.URL, ":")[0]
+
+ c := ts.Client()
+ c.Transport.(*Transport).Dial = func(_ string, _ string) (net.Conn, error) {
+ return net.Dial("tcp", ts.Listener.Addr().String())
+ }
+
+ req, _ := NewRequest("GET", proto+"://a.example.com/", nil)
+ req.Header.Add("Cookie", "foo=bar")
+ req.Header.Add("Authorization", "secretpassword")
+ res, err := c.Do(req)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.Header.Get("X-Done") != "true" {
+ t.Fatalf("response missing expected header: X-Done=true")
+ }
+}
+
// Issue 22233: copy host when Client follows a relative redirect.
func TestClientCopyHostOnRedirect(t *testing.T) {
// Virtual hostname: should not receive any request.
@@ -1696,43 +1753,39 @@ func TestClientAltersCookiesOnRedirect(t *testing.T) {
// Part of Issue 4800
func TestShouldCopyHeaderOnRedirect(t *testing.T) {
tests := []struct {
- header string
initialURL string
destURL string
want bool
}{
- {"User-Agent", "http://foo.com/", "http://bar.com/", true},
- {"X-Foo", "http://foo.com/", "http://bar.com/", true},
-
// Sensitive headers:
- {"cookie", "http://foo.com/", "http://bar.com/", false},
- {"cookie2", "http://foo.com/", "http://bar.com/", false},
- {"authorization", "http://foo.com/", "http://bar.com/", false},
- {"authorization", "http://foo.com/", "https://foo.com/", true},
- {"authorization", "http://foo.com:1234/", "http://foo.com:4321/", true},
- {"www-authenticate", "http://foo.com/", "http://bar.com/", false},
- {"authorization", "http://foo.com/", "http://[::1%25.foo.com]/", false},
+ {"http://foo.com/", "http://bar.com/", false},
+ {"http://foo.com/", "http://bar.com/", false},
+ {"http://foo.com/", "http://bar.com/", false},
+ {"http://foo.com/", "https://foo.com/", true},
+ {"http://foo.com:1234/", "http://foo.com:4321/", true},
+ {"http://foo.com/", "http://bar.com/", false},
+ {"http://foo.com/", "http://[::1%25.foo.com]/", false},
// But subdomains should work:
- {"www-authenticate", "http://foo.com/", "http://foo.com/", true},
- {"www-authenticate", "http://foo.com/", "http://sub.foo.com/", true},
- {"www-authenticate", "http://foo.com/", "http://notfoo.com/", false},
- {"www-authenticate", "http://foo.com/", "https://foo.com/", true},
- {"www-authenticate", "http://foo.com:80/", "http://foo.com/", true},
- {"www-authenticate", "http://foo.com:80/", "http://sub.foo.com/", true},
- {"www-authenticate", "http://foo.com:443/", "https://foo.com/", true},
- {"www-authenticate", "http://foo.com:443/", "https://sub.foo.com/", true},
- {"www-authenticate", "http://foo.com:1234/", "http://foo.com/", true},
-
- {"authorization", "http://foo.com/", "http://foo.com/", true},
- {"authorization", "http://foo.com/", "http://sub.foo.com/", true},
- {"authorization", "http://foo.com/", "http://notfoo.com/", false},
- {"authorization", "http://foo.com/", "https://foo.com/", true},
- {"authorization", "http://foo.com:80/", "http://foo.com/", true},
- {"authorization", "http://foo.com:80/", "http://sub.foo.com/", true},
- {"authorization", "http://foo.com:443/", "https://foo.com/", true},
- {"authorization", "http://foo.com:443/", "https://sub.foo.com/", true},
- {"authorization", "http://foo.com:1234/", "http://foo.com/", true},
+ {"http://foo.com/", "http://foo.com/", true},
+ {"http://foo.com/", "http://sub.foo.com/", true},
+ {"http://foo.com/", "http://notfoo.com/", false},
+ {"http://foo.com/", "https://foo.com/", true},
+ {"http://foo.com:80/", "http://foo.com/", true},
+ {"http://foo.com:80/", "http://sub.foo.com/", true},
+ {"http://foo.com:443/", "https://foo.com/", true},
+ {"http://foo.com:443/", "https://sub.foo.com/", true},
+ {"http://foo.com:1234/", "http://foo.com/", true},
+
+ {"http://foo.com/", "http://foo.com/", true},
+ {"http://foo.com/", "http://sub.foo.com/", true},
+ {"http://foo.com/", "http://notfoo.com/", false},
+ {"http://foo.com/", "https://foo.com/", true},
+ {"http://foo.com:80/", "http://foo.com/", true},
+ {"http://foo.com:80/", "http://sub.foo.com/", true},
+ {"http://foo.com:443/", "https://foo.com/", true},
+ {"http://foo.com:443/", "https://sub.foo.com/", true},
+ {"http://foo.com:1234/", "http://foo.com/", true},
}
for i, tt := range tests {
u0, err := url.Parse(tt.initialURL)
@@ -1745,10 +1798,10 @@ func TestShouldCopyHeaderOnRedirect(t *testing.T) {
t.Errorf("%d. dest URL %q parse error: %v", i, tt.destURL, err)
continue
}
- got := Export_shouldCopyHeaderOnRedirect(tt.header, u0, u1)
+ got := Export_shouldCopyHeaderOnRedirect(u0, u1)
if got != tt.want {
- t.Errorf("%d. shouldCopyHeaderOnRedirect(%q, %q => %q) = %v; want %v",
- i, tt.header, tt.initialURL, tt.destURL, got, tt.want)
+ t.Errorf("%d. shouldCopyHeaderOnRedirect(%q => %q) = %v; want %v",
+ i, tt.initialURL, tt.destURL, got, tt.want)
}
}
}
diff --git a/src/net/http/internal/testcert/testcert.go b/src/net/http/internal/testcert/testcert.go
index d510e79..78ce42e 100644
--- a/src/net/http/internal/testcert/testcert.go
+++ b/src/net/http/internal/testcert/testcert.go
@@ -10,37 +10,56 @@ import "strings"
// LocalhostCert is a PEM-encoded TLS cert with SAN IPs
// "127.0.0.1" and "[::1]", expiring at Jan 29 16:00:00 2084 GMT.
// generated from src/crypto/tls:
-// go run generate_cert.go --rsa-bits 1024 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
+// go run generate_cert.go --rsa-bits 2048 --host 127.0.0.1,::1,example.com,*.example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
var LocalhostCert = []byte(`-----BEGIN CERTIFICATE-----
-MIICEzCCAXygAwIBAgIQMIMChMLGrR+QvmQvpwAU6zANBgkqhkiG9w0BAQsFADAS
+MIIDSDCCAjCgAwIBAgIQFgSNW7Q203yuk2HUM4z0GDANBgkqhkiG9w0BAQsFADAS
MRAwDgYDVQQKEwdBY21lIENvMCAXDTcwMDEwMTAwMDAwMFoYDzIwODQwMTI5MTYw
-MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
-iQKBgQDuLnQAI3mDgey3VBzWnB2L39JUU4txjeVE6myuDqkM/uGlfjb9SjY1bIw4
-iA5sBBZzHi3z0h1YV8QPuxEbi4nW91IJm2gsvvZhIrCHS3l6afab4pZBl2+XsDul
-rKBxKKtD1rGxlG4LjncdabFn9gvLZad2bSysqz/qTAUStTvqJQIDAQABo2gwZjAO
-BgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUw
-AwEB/zAuBgNVHREEJzAlggtleGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAA
-AAAAATANBgkqhkiG9w0BAQsFAAOBgQCEcetwO59EWk7WiJsG4x8SY+UIAA+flUI9
-tyC4lNhbcF2Idq9greZwbYCqTTTr2XiRNSMLCOjKyI7ukPoPjo16ocHj+P3vZGfs
-h1fIw3cSS2OolhloGw/XM6RWPWtPAlGykKLciQrBru5NAPvCMsb/I1DAceTiotQM
-fblo6RBxUQ==
+MDAwWjASMRAwDgYDVQQKEwdBY21lIENvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAqspE6oCu4tLTgAca17wS9FecmXBWM2+qzz5dmvQAI25qf4xo0vKC
+/apwhh8pHO0S3IOHcILAy8j9e/cs1V8k0Dre7KGNqqZyNCc7950ZQtt/CRN1H8MF
+vAh20qsXC7BQjfE0Ga522d1UTUU0rAAhQk9Ityp4hy5f7RjXMbEJphgmtg1qZBnS
++Uahsiky1L6hmUdjWMKZYaS14X+N3MhGWjR2R2hiP/QMEb7Y9ReCd2sRqWTjKyXJ
+i5JD1+tVJgUeBJp4+38naVT3LG/VviIOE9xo4WhrtsnX9adm6ctcxPIFrPRWIhyV
+RSfQwHo26mJiGH2KsmM3gggX/W9E0ft6UQIDAQABo4GXMIGUMA4GA1UdDwEB/wQE
+AwICpDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBT46lXgr7Azh/gy8zDLaq8oCpGCmzA9BgNVHREENjA0ggtleGFtcGxlLmNv
+bYINKi5leGFtcGxlLmNvbYcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG
+9w0BAQsFAAOCAQEATM2XXLR3gTagL5MXK29RloJRD/vyZNiKL3Fuj/EOaU53Mpm2
+MJ7b7WTz4Kft285UaFqeSSTnOkDmlSPmccI2v7Ridp7gO3RimPz5Ofd1zLw12zEx
+4ZzFjU6vuLUwfw+1lw8xnS7cn1j2Q5AoWmfJxnQKCnkX487m/16szda49ydTestc
+s4g18dV/OGhWOQpLA2Z75DAu2rmE1oLKTrmYc36xjGXqMqSB33QU0sHgtkopuWdC
+C1TGa/ZwgQLdNPZfbdrYqtJQrnlyxSLx9R/ZZH00zse2N1eY0qPje2yXjNkD10Lp
+DXa5YlHo2skMtBMQ8uq+nQ+gWhRu5CJ2OYajVg==
-----END CERTIFICATE-----`)
// LocalhostKey is the private key for LocalhostCert.
var LocalhostKey = []byte(testingKey(`-----BEGIN RSA TESTING KEY-----
-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
+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
+WlHTZvq5FrvuRL63przviPPw
-----END RSA TESTING KEY-----`))
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }

View File

@ -0,0 +1,217 @@
From b01fddf727a610033e03814d5b96abceab71c989 Mon Sep 17 00:00:00 2001
From: wujichao <wujichao1@huawei.com>
Date: Mon, 24 Feb 2025 15:09:33 +0800
Subject: [PATCH] 0027-crypto-tls-fix-Config.Time-in-tests-using-expired-ce
---
src/crypto/tls/handshake_client_test.go | 30 ++++++++++++++-----------
src/crypto/tls/handshake_server_test.go | 2 ++
src/crypto/tls/handshake_test.go | 5 +++++
src/crypto/tls/tls_test.go | 4 +---
4 files changed, 25 insertions(+), 16 deletions(-)
diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go
index d581cb1..5538202 100644
--- a/src/crypto/tls/handshake_client_test.go
+++ b/src/crypto/tls/handshake_client_test.go
@@ -881,6 +881,7 @@ func testResumption(t *testing.T, version uint16) {
MaxVersion: version,
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
Certificates: testConfig.Certificates,
+ Time: testTime,
}
issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
@@ -897,6 +898,7 @@ func testResumption(t *testing.T, version uint16) {
ClientSessionCache: NewLRUClientSessionCache(32),
RootCAs: rootCAs,
ServerName: "example.golang",
+ Time: testTime,
}
testResumeState := func(test string, didResume bool) {
@@ -944,20 +946,20 @@ func testResumption(t *testing.T, version uint16) {
}
// An old session ticket can resume, but the server will provide a ticket encrypted with a fresh key.
- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) }
+ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) }
testResumeState("ResumeWithOldTicket", true)
if bytes.Equal(ticket[:ticketKeyNameLen], getTicket()[:ticketKeyNameLen]) {
t.Fatal("old first ticket matches the fresh one")
}
// Now the session tickey key is expired, so a full handshake should occur.
- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) }
+ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + time.Minute) }
testResumeState("ResumeWithExpiredTicket", false)
if bytes.Equal(ticket, getTicket()) {
t.Fatal("expired first ticket matches the fresh one")
}
- serverConfig.Time = func() time.Time { return time.Now() } // reset the time back
+ serverConfig.Time = testTime // reset the time back
key1 := randomKey()
serverConfig.SetSessionTicketKeys([][32]byte{key1})
@@ -974,11 +976,11 @@ func testResumption(t *testing.T, version uint16) {
testResumeState("KeyChangeFinish", true)
// Age the session ticket a bit, but not yet expired.
- serverConfig.Time = func() time.Time { return time.Now().Add(24*time.Hour + time.Minute) }
+ serverConfig.Time = func() time.Time { return testTime().Add(24*time.Hour + time.Minute) }
testResumeState("OldSessionTicket", true)
ticket = getTicket()
// Expire the session ticket, which would force a full handshake.
- serverConfig.Time = func() time.Time { return time.Now().Add(24*8*time.Hour + time.Minute) }
+ serverConfig.Time = func() time.Time { return testTime().Add(24*8*time.Hour + 2*time.Minute) }
testResumeState("ExpiredSessionTicket", false)
if bytes.Equal(ticket, getTicket()) {
t.Fatal("new ticket wasn't provided after old ticket expired")
@@ -988,15 +990,15 @@ func testResumption(t *testing.T, version uint16) {
d := 0 * time.Hour
for i := 0; i < 13; i++ {
d += 12 * time.Hour
- serverConfig.Time = func() time.Time { return time.Now().Add(d) }
+ serverConfig.Time = func() time.Time { return testTime().Add(d) }
testResumeState("OldSessionTicket", true)
}
// Expire it (now a little more than 7 days) and make sure a full
// handshake occurs for TLS 1.2. Resumption should still occur for
// TLS 1.3 since the client should be using a fresh ticket sent over
// by the server.
- d += 12 * time.Hour
- serverConfig.Time = func() time.Time { return time.Now().Add(d) }
+ d += 12*time.Hour + time.Minute
+ serverConfig.Time = func() time.Time { return testTime().Add(d) }
if version == VersionTLS13 {
testResumeState("ExpiredSessionTicket", true)
} else {
@@ -1012,6 +1014,7 @@ func testResumption(t *testing.T, version uint16) {
MaxVersion: version,
CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA},
Certificates: testConfig.Certificates,
+ Time: testTime,
}
serverConfig.SetSessionTicketKeys([][32]byte{key2})
@@ -1698,6 +1701,7 @@ func testVerifyConnection(t *testing.T, version uint16) {
serverConfig := &Config{
MaxVersion: version,
Certificates: []Certificate{testConfig.Certificates[0]},
+ Time: testTime,
ClientCAs: rootCAs,
NextProtos: []string{"protocol1"},
}
@@ -1711,6 +1715,7 @@ func testVerifyConnection(t *testing.T, version uint16) {
RootCAs: rootCAs,
ServerName: "example.golang",
Certificates: []Certificate{testConfig.Certificates[0]},
+ Time: testTime,
NextProtos: []string{"protocol1"},
}
test.configureClient(clientConfig, &clientCalled)
@@ -1753,8 +1758,6 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) {
rootCAs := x509.NewCertPool()
rootCAs.AddCert(issuer)
- now := func() time.Time { return time.Unix(1476984729, 0) }
-
sentinelErr := errors.New("TestVerifyPeerCertificate")
verifyPeerCertificateCallback := func(called *bool, rawCerts [][]byte, validatedChains [][]*x509.Certificate) error {
@@ -2000,7 +2003,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) {
config.ServerName = "example.golang"
config.ClientAuth = RequireAndVerifyClientCert
config.ClientCAs = rootCAs
- config.Time = now
+ config.Time = testTime
config.MaxVersion = version
config.Certificates = make([]Certificate, 1)
config.Certificates[0].Certificate = [][]byte{testRSACertificate}
@@ -2017,7 +2020,7 @@ func testVerifyPeerCertificate(t *testing.T, version uint16) {
config := testConfig.Clone()
config.ServerName = "example.golang"
config.RootCAs = rootCAs
- config.Time = now
+ config.Time = testTime
config.MaxVersion = version
test.configureClient(config, &clientCalled)
clientErr := Client(c, config).Handshake()
@@ -2330,7 +2333,7 @@ func testGetClientCertificate(t *testing.T, version uint16) {
serverConfig.RootCAs = x509.NewCertPool()
serverConfig.RootCAs.AddCert(issuer)
serverConfig.ClientCAs = serverConfig.RootCAs
- serverConfig.Time = func() time.Time { return time.Unix(1476984729, 0) }
+ serverConfig.Time = testTime
serverConfig.MaxVersion = version
clientConfig := testConfig.Clone()
@@ -2501,6 +2504,7 @@ func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
ClientSessionCache: NewLRUClientSessionCache(32),
ServerName: "example.golang",
RootCAs: roots,
+ Time: testTime,
}
serverConfig := testConfig.Clone()
serverConfig.MaxVersion = ver
diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go
index 3d23b3f..72f0327 100644
--- a/src/crypto/tls/handshake_server_test.go
+++ b/src/crypto/tls/handshake_server_test.go
@@ -481,12 +481,14 @@ func testCrossVersionResume(t *testing.T, version uint16) {
serverConfig := &Config{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
Certificates: testConfig.Certificates,
+ Time: testTime,
}
clientConfig := &Config{
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
InsecureSkipVerify: true,
ClientSessionCache: NewLRUClientSessionCache(1),
ServerName: "servername",
+ Time: testTime,
}
// Establish a session at TLS 1.1.
diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go
index 9bfb117..988c2e3 100644
--- a/src/crypto/tls/handshake_test.go
+++ b/src/crypto/tls/handshake_test.go
@@ -428,6 +428,11 @@ func fromHex(s string) []byte {
return b
}
+// testTime is 2016-10-20T17:32:09.000Z, which is within the validity period of
+// [testRSACertificate], [testRSACertificateIssuer], [testRSA2048Certificate],
+// [testRSA2048CertificateIssuer], and [testECDSACertificate].
+var testTime = func() time.Time { return time.Unix(1476984729, 0) }
+
var testRSACertificate = fromHex("3082024b308201b4a003020102020900e8f09d3fe25beaa6300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301a310b3009060355040a1302476f310b300906035504031302476f30819f300d06092a864886f70d010101050003818d0030818902818100db467d932e12270648bc062821ab7ec4b6a25dfe1e5245887a3647a5080d92425bc281c0be97799840fb4f6d14fd2b138bc2a52e67d8d4099ed62238b74a0b74732bc234f1d193e596d9747bf3589f6c613cc0b041d4d92b2b2423775b1c3bbd755dce2054cfa163871d1e24c4f31d1a508baab61443ed97a77562f414c852d70203010001a38193308190300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff0402300030190603551d0e041204109f91161f43433e49a6de6db680d79f60301b0603551d230414301280104813494d137e1631bba301d5acab6e7b30190603551d1104123010820e6578616d706c652e676f6c616e67300d06092a864886f70d01010b0500038181009d30cc402b5b50a061cbbae55358e1ed8328a9581aa938a495a1ac315a1a84663d43d32dd90bf297dfd320643892243a00bccf9c7db74020015faad3166109a276fd13c3cce10c5ceeb18782f16c04ed73bbb343778d0c1cf10fa1d8408361c94c722b9daedb4606064df4c1b33ec0d1bd42d4dbfe3d1360845c21d33be9fae7")
var testRSACertificateIssuer = fromHex("3082021930820182a003020102020900ca5e4e811a965964300d06092a864886f70d01010b0500301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f74301e170d3136303130313030303030305a170d3235303130313030303030305a301f310b3009060355040a1302476f3110300e06035504031307476f20526f6f7430819f300d06092a864886f70d010101050003818d0030818902818100d667b378bb22f34143b6cd2008236abefaf2852adf3ab05e01329e2c14834f5105df3f3073f99dab5442d45ee5f8f57b0111c8cb682fbb719a86944eebfffef3406206d898b8c1b1887797c9c5006547bb8f00e694b7a063f10839f269f2c34fff7a1f4b21fbcd6bfdfb13ac792d1d11f277b5c5b48600992203059f2a8f8cc50203010001a35d305b300e0603551d0f0101ff040403020204301d0603551d250416301406082b0601050507030106082b06010505070302300f0603551d130101ff040530030101ff30190603551d0e041204104813494d137e1631bba301d5acab6e7b300d06092a864886f70d01010b050003818100c1154b4bab5266221f293766ae4138899bd4c5e36b13cee670ceeaa4cbdf4f6679017e2fe649765af545749fe4249418a56bd38a04b81e261f5ce86b8d5c65413156a50d12449554748c59a30c515bc36a59d38bddf51173e899820b282e40aa78c806526fd184fb6b4cf186ec728edffa585440d2b3225325f7ab580e87dd76")
diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go
index d8a43ad..5fa6e90 100644
--- a/src/crypto/tls/tls_test.go
+++ b/src/crypto/tls/tls_test.go
@@ -1058,8 +1058,6 @@ func TestConnectionState(t *testing.T) {
rootCAs := x509.NewCertPool()
rootCAs.AddCert(issuer)
- now := func() time.Time { return time.Unix(1476984729, 0) }
-
const alpnProtocol = "golang"
const serverName = "example.golang"
var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")}
@@ -1075,7 +1073,7 @@ func TestConnectionState(t *testing.T) {
}
t.Run(name, func(t *testing.T) {
config := &Config{
- Time: now,
+ Time: testTime,
Rand: zeroSource{},
Certificates: make([]Certificate, 1),
MaxVersion: v,
--
2.33.0

View File

@ -63,7 +63,7 @@
Name: golang
Version: 1.17.3
Release: 37
Release: 38
Summary: The Go Programming Language
License: BSD and Public Domain
URL: https://golang.org/
@ -220,6 +220,9 @@ Patch6067: 0067-Backport-net-http-send-body-or-close-connection-on-e.patch
Patch6068: 0068-Backport-go-parser-track-depth-in-nested-element-lis.patch
Patch6069: 0069-Backport-encoding-gob-cover-missed-cases-when-checki.patch
Patch6070: 0070-Backport-go-build-constraint-add-parsing-limits.patch
Patch6071: 0071-CVE-2024-45341-crypto-x509-properly-check-for-IPv6-h.patch
Patch6072: 0072-CVE-2024-45336-net-http-persist-header-stripping-acr.patch
Patch6073: 0073-crypto-tls-fix-Config.Time-in-tests-using-expir.patch
ExclusiveArch: %{golang_arches}
@ -458,6 +461,12 @@ fi
%files devel -f go-tests.list -f go-misc.list -f go-src.list
%changelog
* Fri Feb 21 2025 wujichao <wujichao1@huawei.com> - 1.17.3-38
- Type:CVE
- CVE:CVE-2024-45341 CVE-2024-45336
- SUG:NA
- DESC:fix CVE-2024-45341 CVE-2024-45336
* Tue Oct 22 2024 hanchao <hanchao63@huawei.com> - 1.17.3-37
- Type:CVE
- CVE:CVE-2024-34156,CVE-2024-34158