Compare commits
5 Commits
Author | SHA1 | Date |
---|---|---|
Jakub Čajka | 029fcc33fa | |
Jakub Čajka | 2bde97f8e2 | |
Jakub Čajka | 28634a4d32 | |
Jakub Čajka | d476528d36 | |
Jakub Čajka | d332d245fc |
|
@ -27,3 +27,4 @@
|
|||
/go1.5.2.src.tar.gz
|
||||
/Mark.Twain-Tom.Sawyer.txt.bz2
|
||||
/go1.5.3.src.tar.gz
|
||||
/go1.5.4.src.tar.gz
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
From a357d15e9ee36a1232ae071d9968c4cf10a672b4 Mon Sep 17 00:00:00 2001
|
||||
From: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
Date: Mon, 18 Jul 2016 06:05:24 +0000
|
||||
Subject: [PATCH] [release-branch.go1.6] net/http, net/http/cgi: fix for CGI +
|
||||
HTTP_PROXY security issue
|
||||
|
||||
Because,
|
||||
|
||||
* The CGI spec defines that incoming request header "Foo: Bar" maps to
|
||||
environment variable HTTP_FOO == "Bar". (see RFC 3875 4.1.18)
|
||||
|
||||
* The HTTP_PROXY environment variable is conventionally used to configure
|
||||
the HTTP proxy for HTTP clients (and is respected by default for
|
||||
Go's net/http.Client and Transport)
|
||||
|
||||
That means Go programs running in a CGI environment (as a child
|
||||
process under a CGI host) are vulnerable to an incoming request
|
||||
containing "Proxy: attacker.com:1234", setting HTTP_PROXY, and
|
||||
changing where Go by default proxies all outbound HTTP requests.
|
||||
|
||||
This is CVE-2016-5386, aka https://httpoxy.org/
|
||||
|
||||
Fixes #16405
|
||||
|
||||
Change-Id: I6f68ade85421b4807785799f6d98a8b077e871f0
|
||||
Reviewed-on: https://go-review.googlesource.com/25010
|
||||
Run-TryBot: Chris Broadfoot <cbro@golang.org>
|
||||
TryBot-Result: Gobot Gobot <gobot@golang.org>
|
||||
Reviewed-by: Chris Broadfoot <cbro@golang.org>
|
||||
Reviewed-on: https://go-review.googlesource.com/25012
|
||||
---
|
||||
src/net/http/cgi/host.go | 4 ++++
|
||||
src/net/http/cgi/host_test.go | 37 ++++++++++++++++++++++++++++++++++---
|
||||
src/net/http/transport.go | 3 +++
|
||||
src/net/http/transport_test.go | 14 +++++++++++++-
|
||||
4 files changed, 54 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/net/http/cgi/host.go b/src/net/http/cgi/host.go
|
||||
index 9b4d875..3f1600b 100644
|
||||
--- a/src/net/http/cgi/host.go
|
||||
+++ b/src/net/http/cgi/host.go
|
||||
@@ -145,6 +145,10 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
for k, v := range req.Header {
|
||||
k = strings.Map(upperCaseAndUnderscore, k)
|
||||
+ if k == "PROXY" {
|
||||
+ // See Issue 16405
|
||||
+ continue
|
||||
+ }
|
||||
joinStr := ", "
|
||||
if k == "COOKIE" {
|
||||
joinStr = "; "
|
||||
diff --git a/src/net/http/cgi/host_test.go b/src/net/http/cgi/host_test.go
|
||||
index 3327764..2783fe1 100644
|
||||
--- a/src/net/http/cgi/host_test.go
|
||||
+++ b/src/net/http/cgi/host_test.go
|
||||
@@ -34,15 +34,18 @@ func newRequest(httpreq string) *http.Request {
|
||||
return req
|
||||
}
|
||||
|
||||
-func runCgiTest(t *testing.T, h *Handler, httpreq string, expectedMap map[string]string) *httptest.ResponseRecorder {
|
||||
+func runCgiTest(t *testing.T, h *Handler,
|
||||
+ httpreq string,
|
||||
+ expectedMap map[string]string, checks ...func(reqInfo map[string]string)) *httptest.ResponseRecorder {
|
||||
rw := httptest.NewRecorder()
|
||||
req := newRequest(httpreq)
|
||||
h.ServeHTTP(rw, req)
|
||||
- runResponseChecks(t, rw, expectedMap)
|
||||
+ runResponseChecks(t, rw, expectedMap, checks...)
|
||||
return rw
|
||||
}
|
||||
|
||||
-func runResponseChecks(t *testing.T, rw *httptest.ResponseRecorder, expectedMap map[string]string) {
|
||||
+func runResponseChecks(t *testing.T, rw *httptest.ResponseRecorder,
|
||||
+ expectedMap map[string]string, checks ...func(reqInfo map[string]string)) {
|
||||
// Make a map to hold the test map that the CGI returns.
|
||||
m := make(map[string]string)
|
||||
m["_body"] = rw.Body.String()
|
||||
@@ -80,6 +83,9 @@ readlines:
|
||||
t.Errorf("for key %q got %q; expected %q", key, got, expected)
|
||||
}
|
||||
}
|
||||
+ for _, check := range checks {
|
||||
+ check(m)
|
||||
+ }
|
||||
}
|
||||
|
||||
var cgiTested, cgiWorks bool
|
||||
@@ -235,6 +241,31 @@ func TestDupHeaders(t *testing.T) {
|
||||
expectedMap)
|
||||
}
|
||||
|
||||
+// Issue 16405: CGI+http.Transport differing uses of HTTP_PROXY.
|
||||
+// Verify we don't set the HTTP_PROXY environment variable.
|
||||
+// Hope nobody was depending on it. It's not a known header, though.
|
||||
+func TestDropProxyHeader(t *testing.T) {
|
||||
+ check(t)
|
||||
+ h := &Handler{
|
||||
+ Path: "testdata/test.cgi",
|
||||
+ }
|
||||
+ expectedMap := map[string]string{
|
||||
+ "env-REQUEST_URI": "/myscript/bar?a=b",
|
||||
+ "env-SCRIPT_FILENAME": "testdata/test.cgi",
|
||||
+ "env-HTTP_X_FOO": "a",
|
||||
+ }
|
||||
+ runCgiTest(t, h, "GET /myscript/bar?a=b HTTP/1.0\n"+
|
||||
+ "X-Foo: a\n"+
|
||||
+ "Proxy: should_be_stripped\n"+
|
||||
+ "Host: example.com\n\n",
|
||||
+ expectedMap,
|
||||
+ func(reqInfo map[string]string) {
|
||||
+ if v, ok := reqInfo["env-HTTP_PROXY"]; ok {
|
||||
+ t.Errorf("HTTP_PROXY = %q; should be absent", v)
|
||||
+ }
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
func TestPathInfoNoRoot(t *testing.T) {
|
||||
check(t)
|
||||
h := &Handler{
|
||||
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
|
||||
index 1e3ea11..794b786 100644
|
||||
--- a/src/net/http/transport.go
|
||||
+++ b/src/net/http/transport.go
|
||||
@@ -216,6 +216,9 @@ func ProxyFromEnvironment(req *Request) (*url.URL, error) {
|
||||
}
|
||||
if proxy == "" {
|
||||
proxy = httpProxyEnv.Get()
|
||||
+ if proxy != "" && os.Getenv("REQUEST_METHOD") != "" {
|
||||
+ return nil, errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")
|
||||
+ }
|
||||
}
|
||||
if proxy == "" {
|
||||
return nil, nil
|
||||
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
|
||||
index d9da078..381432e 100644
|
||||
--- a/src/net/http/transport_test.go
|
||||
+++ b/src/net/http/transport_test.go
|
||||
@@ -1985,7 +1985,8 @@ type proxyFromEnvTest struct {
|
||||
|
||||
env string // HTTP_PROXY
|
||||
httpsenv string // HTTPS_PROXY
|
||||
- noenv string // NO_RPXY
|
||||
+ noenv string // NO_PROXY
|
||||
+ reqmeth string // REQUEST_METHOD
|
||||
|
||||
want string
|
||||
wanterr error
|
||||
@@ -2009,6 +2010,10 @@ func (t proxyFromEnvTest) String() string {
|
||||
space()
|
||||
fmt.Fprintf(&buf, "no_proxy=%q", t.noenv)
|
||||
}
|
||||
+ if t.reqmeth != "" {
|
||||
+ space()
|
||||
+ fmt.Fprintf(&buf, "request_method=%q", t.reqmeth)
|
||||
+ }
|
||||
req := "http://example.com"
|
||||
if t.req != "" {
|
||||
req = t.req
|
||||
@@ -2032,6 +2037,12 @@ var proxyFromEnvTests = []proxyFromEnvTest{
|
||||
{req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "secure.proxy.tld", want: "http://secure.proxy.tld"},
|
||||
{req: "https://secure.tld/", env: "http.proxy.tld", httpsenv: "https://secure.proxy.tld", want: "https://secure.proxy.tld"},
|
||||
|
||||
+ // Issue 16405: don't use HTTP_PROXY in a CGI environment,
|
||||
+ // where HTTP_PROXY can be attacker-controlled.
|
||||
+ {env: "http://10.1.2.3:8080", reqmeth: "POST",
|
||||
+ want: "<nil>",
|
||||
+ wanterr: errors.New("net/http: refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy")},
|
||||
+
|
||||
{want: "<nil>"},
|
||||
|
||||
{noenv: "example.com", req: "http://example.com/", env: "proxy", want: "<nil>"},
|
||||
@@ -2047,6 +2058,7 @@ func TestProxyFromEnvironment(t *testing.T) {
|
||||
os.Setenv("HTTP_PROXY", tt.env)
|
||||
os.Setenv("HTTPS_PROXY", tt.httpsenv)
|
||||
os.Setenv("NO_PROXY", tt.noenv)
|
||||
+ os.Setenv("REQUEST_METHOD", tt.reqmeth)
|
||||
ResetCachedEnvironment()
|
||||
reqURL := tt.req
|
||||
if reqURL == "" {
|
|
@ -0,0 +1,459 @@
|
|||
From 7a75a55cc44b92836f342e9eeb0f5b1ce20821eb Mon Sep 17 00:00:00 2001
|
||||
From: Quentin Smith <quentin@golang.org>
|
||||
Date: Wed, 30 Nov 2016 15:16:37 -0500
|
||||
Subject: [PATCH 3/4] [release-branch.go1.6] crypto/x509: read Darwin trust
|
||||
settings for root CAs
|
||||
|
||||
Darwin separately stores bits indicating whether a root certificate
|
||||
should be trusted; this changes Go to read and use those when
|
||||
initializing SystemCertPool.
|
||||
|
||||
Unfortunately, the trust API is very slow. To avoid a delay of up to
|
||||
0.5s in initializing the system cert pool, we assume that
|
||||
the trust settings found in kSecTrustSettingsDomainSystem will always
|
||||
indicate trust. (That is, all root certs Apple distributes are trusted.)
|
||||
This is not guaranteed by the API but is true in practice.
|
||||
|
||||
In the non-cgo codepath, we do not have that benefit, so we must check
|
||||
the trust status of every certificate. This causes about 0.5s of delay
|
||||
in initializing the SystemCertPool.
|
||||
|
||||
On OS X 10.11 and older, the "security" command requires a certificate
|
||||
to be provided in a file and not on stdin, so the non-cgo codepath
|
||||
creates temporary files for each certificate, further slowing initialization.
|
||||
|
||||
Updates #18141.
|
||||
|
||||
Change-Id: If681c514047afe5e1a68de6c9d40ceabbce54755
|
||||
Reviewed-on: https://go-review.googlesource.com/33721
|
||||
Run-TryBot: Quentin Smith <quentin@golang.org>
|
||||
TryBot-Result: Gobot Gobot <gobot@golang.org>
|
||||
Reviewed-by: Russ Cox <rsc@golang.org>
|
||||
Reviewed-on: https://go-review.googlesource.com/33728
|
||||
---
|
||||
src/crypto/x509/cert_pool.go | 15 +++
|
||||
src/crypto/x509/root_cgo_darwin.go | 184 +++++++++++++++++++++++++++++++++---
|
||||
src/crypto/x509/root_darwin.go | 114 +++++++++++++++++++++-
|
||||
src/crypto/x509/root_darwin_test.go | 1 +
|
||||
4 files changed, 296 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go
|
||||
index 2362e84..dc88ad4 100644
|
||||
--- a/src/crypto/x509/cert_pool.go
|
||||
+++ b/src/crypto/x509/cert_pool.go
|
||||
@@ -52,6 +52,21 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCer
|
||||
return
|
||||
}
|
||||
|
||||
+func (s *CertPool) contains(cert *Certificate) bool {
|
||||
+ if s == nil {
|
||||
+ return false
|
||||
+ }
|
||||
+
|
||||
+ candidates := s.byName[string(cert.RawSubject)]
|
||||
+ for _, c := range candidates {
|
||||
+ if s.certs[c].Equal(cert) {
|
||||
+ return true
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false
|
||||
+}
|
||||
+
|
||||
// AddCert adds a certificate to a pool.
|
||||
func (s *CertPool) AddCert(cert *Certificate) {
|
||||
if cert == nil {
|
||||
diff --git a/src/crypto/x509/root_cgo_darwin.go b/src/crypto/x509/root_cgo_darwin.go
|
||||
index bf4a5cd..ee94dad 100644
|
||||
--- a/src/crypto/x509/root_cgo_darwin.go
|
||||
+++ b/src/crypto/x509/root_cgo_darwin.go
|
||||
@@ -7,30 +7,28 @@
|
||||
package x509
|
||||
|
||||
/*
|
||||
-#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
|
||||
+#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1080
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||
|
||||
+#include <errno.h>
|
||||
+#include <sys/sysctl.h>
|
||||
+
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
|
||||
-// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
|
||||
-//
|
||||
-// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
|
||||
-// certificates of the system. On failure, the function returns -1.
|
||||
-//
|
||||
-// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
|
||||
-// we've consumed its content.
|
||||
-int FetchPEMRoots(CFDataRef *pemRoots) {
|
||||
+// FetchPEMRoots_MountainLion is the version of FetchPEMRoots from Go 1.6
|
||||
+// which still works on OS X 10.8 (Mountain Lion).
|
||||
+// It lacks support for admin & user cert domains.
|
||||
+// See golang.org/issue/16473
|
||||
+int FetchPEMRoots_MountainLion(CFDataRef *pemRoots) {
|
||||
if (pemRoots == NULL) {
|
||||
return -1;
|
||||
}
|
||||
-
|
||||
CFArrayRef certs = NULL;
|
||||
OSStatus err = SecTrustCopyAnchorCertificates(&certs);
|
||||
if (err != noErr) {
|
||||
return -1;
|
||||
}
|
||||
-
|
||||
CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
int i, ncerts = CFArrayGetCount(certs);
|
||||
for (i = 0; i < ncerts; i++) {
|
||||
@@ -39,7 +37,6 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
|
||||
if (cert == NULL) {
|
||||
continue;
|
||||
}
|
||||
-
|
||||
// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
|
||||
// Once we support weak imports via cgo we should prefer that, and fall back to this
|
||||
// for older systems.
|
||||
@@ -47,16 +44,157 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
|
||||
if (err != noErr) {
|
||||
continue;
|
||||
}
|
||||
-
|
||||
if (data != NULL) {
|
||||
CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
|
||||
CFRelease(data);
|
||||
}
|
||||
}
|
||||
-
|
||||
CFRelease(certs);
|
||||
+ *pemRoots = combinedData;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+// useOldCode reports whether the running machine is OS X 10.8 Mountain Lion
|
||||
+// or older. We only support Mountain Lion and higher, but we'll at least try our
|
||||
+// best on older machines and continue to use the old code path.
|
||||
+//
|
||||
+// See golang.org/issue/16473
|
||||
+int useOldCode() {
|
||||
+ char str[256];
|
||||
+ size_t size = sizeof(str);
|
||||
+ memset(str, 0, size);
|
||||
+ sysctlbyname("kern.osrelease", str, &size, NULL, 0);
|
||||
+ // OS X 10.8 is osrelease "12.*", 10.7 is 11.*, 10.6 is 10.*.
|
||||
+ // We never supported things before that.
|
||||
+ return memcmp(str, "12.", 3) == 0 || memcmp(str, "11.", 3) == 0 || memcmp(str, "10.", 3) == 0;
|
||||
+}
|
||||
|
||||
+// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
|
||||
+//
|
||||
+// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
|
||||
+// certificates of the system. On failure, the function returns -1.
|
||||
+// Additionally, it fills untrustedPemRoots with certs that must be removed from pemRoots.
|
||||
+//
|
||||
+// Note: The CFDataRef returned in pemRoots and untrustedPemRoots must
|
||||
+// be released (using CFRelease) after we've consumed its content.
|
||||
+int FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
|
||||
+ if (useOldCode()) {
|
||||
+ return FetchPEMRoots_MountainLion(pemRoots);
|
||||
+ }
|
||||
+
|
||||
+ // Get certificates from all domains, not just System, this lets
|
||||
+ // the user add CAs to their "login" keychain, and Admins to add
|
||||
+ // to the "System" keychain
|
||||
+ SecTrustSettingsDomain domains[] = { kSecTrustSettingsDomainSystem,
|
||||
+ kSecTrustSettingsDomainAdmin,
|
||||
+ kSecTrustSettingsDomainUser };
|
||||
+
|
||||
+ int numDomains = sizeof(domains)/sizeof(SecTrustSettingsDomain);
|
||||
+ if (pemRoots == NULL) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ // kSecTrustSettingsResult is defined as CFSTR("kSecTrustSettingsResult"),
|
||||
+ // but the Go linker's internal linking mode can't handle CFSTR relocations.
|
||||
+ // Create our own dynamic string instead and release it below.
|
||||
+ CFStringRef policy = CFStringCreateWithCString(NULL, "kSecTrustSettingsResult", kCFStringEncodingUTF8);
|
||||
+
|
||||
+ CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
+ CFMutableDataRef combinedUntrustedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
+ for (int i = 0; i < numDomains; i++) {
|
||||
+ CFArrayRef certs = NULL;
|
||||
+ OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs);
|
||||
+ if (err != noErr) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ CFIndex numCerts = CFArrayGetCount(certs);
|
||||
+ for (int j = 0; j < numCerts; j++) {
|
||||
+ CFDataRef data = NULL;
|
||||
+ CFErrorRef errRef = NULL;
|
||||
+ CFArrayRef trustSettings = NULL;
|
||||
+ SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, j);
|
||||
+ if (cert == NULL) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ // We only want trusted certs.
|
||||
+ int untrusted = 0;
|
||||
+ if (i != 0) {
|
||||
+ // Certs found in the system domain are always trusted. If the user
|
||||
+ // configures "Never Trust" on such a cert, it will also be found in the
|
||||
+ // admin or user domain, causing it to be added to untrustedPemRoots. The
|
||||
+ // Go code will then clean this up.
|
||||
+
|
||||
+ // Trust may be stored in any of the domains. According to Apple's
|
||||
+ // SecTrustServer.c, "user trust settings overrule admin trust settings",
|
||||
+ // so take the last trust settings array we find.
|
||||
+ // Skip the system domain since it is always trusted.
|
||||
+ for (int k = 1; k < numDomains; k++) {
|
||||
+ CFArrayRef domainTrustSettings = NULL;
|
||||
+ err = SecTrustSettingsCopyTrustSettings(cert, domains[k], &domainTrustSettings);
|
||||
+ if (err == errSecSuccess && domainTrustSettings != NULL) {
|
||||
+ if (trustSettings) {
|
||||
+ CFRelease(trustSettings);
|
||||
+ }
|
||||
+ trustSettings = domainTrustSettings;
|
||||
+ }
|
||||
+ }
|
||||
+ if (trustSettings == NULL) {
|
||||
+ // "this certificate must be verified to a known trusted certificate"; aka not a root.
|
||||
+ continue;
|
||||
+ }
|
||||
+ for (CFIndex k = 0; k < CFArrayGetCount(trustSettings); k++) {
|
||||
+ CFNumberRef cfNum;
|
||||
+ CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, k);
|
||||
+ if (CFDictionaryGetValueIfPresent(tSetting, policy, (const void**)&cfNum)){
|
||||
+ SInt32 result = 0;
|
||||
+ CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result);
|
||||
+ // TODO: The rest of the dictionary specifies conditions for evaluation.
|
||||
+ if (result == kSecTrustSettingsResultDeny) {
|
||||
+ untrusted = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ CFRelease(trustSettings);
|
||||
+ }
|
||||
+ // We only want to add Root CAs, so make sure Subject and Issuer Name match
|
||||
+ CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef);
|
||||
+ if (errRef != NULL) {
|
||||
+ CFRelease(errRef);
|
||||
+ continue;
|
||||
+ }
|
||||
+ CFDataRef issuerName = SecCertificateCopyNormalizedIssuerContent(cert, &errRef);
|
||||
+ if (errRef != NULL) {
|
||||
+ CFRelease(subjectName);
|
||||
+ CFRelease(errRef);
|
||||
+ continue;
|
||||
+ }
|
||||
+ Boolean equal = CFEqual(subjectName, issuerName);
|
||||
+ CFRelease(subjectName);
|
||||
+ CFRelease(issuerName);
|
||||
+ if (!equal) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ // Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
|
||||
+ // Once we support weak imports via cgo we should prefer that, and fall back to this
|
||||
+ // for older systems.
|
||||
+ err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
|
||||
+ if (err != noErr) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (data != NULL) {
|
||||
+ CFMutableDataRef appendTo = untrusted ? combinedUntrustedData : combinedData;
|
||||
+ CFDataAppendBytes(appendTo, CFDataGetBytePtr(data), CFDataGetLength(data));
|
||||
+ CFRelease(data);
|
||||
+ }
|
||||
+ }
|
||||
+ CFRelease(certs);
|
||||
+ }
|
||||
+ CFRelease(policy);
|
||||
*pemRoots = combinedData;
|
||||
+ *untrustedPemRoots = combinedUntrustedData;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
@@ -67,7 +205,8 @@ func initSystemRoots() {
|
||||
roots := NewCertPool()
|
||||
|
||||
var data C.CFDataRef = nil
|
||||
- err := C.FetchPEMRoots(&data)
|
||||
+ var untrustedData C.CFDataRef = nil
|
||||
+ err := C.FetchPEMRoots(&data, &untrustedData)
|
||||
if err == -1 {
|
||||
return
|
||||
}
|
||||
@@ -75,5 +214,20 @@ func initSystemRoots() {
|
||||
defer C.CFRelease(C.CFTypeRef(data))
|
||||
buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
|
||||
roots.AppendCertsFromPEM(buf)
|
||||
+ if untrustedData == nil {
|
||||
+ systemRoots = roots
|
||||
+ return
|
||||
+ }
|
||||
+ defer C.CFRelease(C.CFTypeRef(untrustedData))
|
||||
+ buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData)))
|
||||
+ untrustedRoots := NewCertPool()
|
||||
+ untrustedRoots.AppendCertsFromPEM(buf)
|
||||
+
|
||||
+ trustedRoots := NewCertPool()
|
||||
+ for _, c := range roots.certs {
|
||||
+ if !untrustedRoots.contains(c) {
|
||||
+ trustedRoots.AddCert(c)
|
||||
+ }
|
||||
+ }
|
||||
systemRoots = roots
|
||||
}
|
||||
diff --git a/src/crypto/x509/root_darwin.go b/src/crypto/x509/root_darwin.go
|
||||
index 78de56c..59b303d 100644
|
||||
--- a/src/crypto/x509/root_darwin.go
|
||||
+++ b/src/crypto/x509/root_darwin.go
|
||||
@@ -6,12 +6,27 @@
|
||||
|
||||
package x509
|
||||
|
||||
-import "os/exec"
|
||||
+import (
|
||||
+ "bytes"
|
||||
+ "encoding/pem"
|
||||
+ "fmt"
|
||||
+ "io/ioutil"
|
||||
+ "os"
|
||||
+ "os/exec"
|
||||
+ "strconv"
|
||||
+ "sync"
|
||||
+ "syscall"
|
||||
+)
|
||||
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
+// This code is only used when compiling without cgo.
|
||||
+// It is here, instead of root_nocgo_darwin.go, so that tests can check it
|
||||
+// even if the tests are run with cgo enabled.
|
||||
+// The linker will not include these unused functions in binaries built with cgo enabled.
|
||||
+
|
||||
func execSecurityRoots() (*CertPool, error) {
|
||||
cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
|
||||
data, err := cmd.Output()
|
||||
@@ -19,7 +34,100 @@ func execSecurityRoots() (*CertPool, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
- roots := NewCertPool()
|
||||
- roots.AppendCertsFromPEM(data)
|
||||
+ var (
|
||||
+ mu sync.Mutex
|
||||
+ roots = NewCertPool()
|
||||
+ )
|
||||
+ add := func(cert *Certificate) {
|
||||
+ mu.Lock()
|
||||
+ defer mu.Unlock()
|
||||
+ roots.AddCert(cert)
|
||||
+ }
|
||||
+ blockCh := make(chan *pem.Block)
|
||||
+ var wg sync.WaitGroup
|
||||
+ for i := 0; i < 4; i++ {
|
||||
+ wg.Add(1)
|
||||
+ go func() {
|
||||
+ defer wg.Done()
|
||||
+ for block := range blockCh {
|
||||
+ verifyCertWithSystem(block, add)
|
||||
+ }
|
||||
+ }()
|
||||
+ }
|
||||
+ for len(data) > 0 {
|
||||
+ var block *pem.Block
|
||||
+ block, data = pem.Decode(data)
|
||||
+ if block == nil {
|
||||
+ break
|
||||
+ }
|
||||
+ if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
+ continue
|
||||
+ }
|
||||
+ blockCh <- block
|
||||
+ }
|
||||
+ close(blockCh)
|
||||
+ wg.Wait()
|
||||
return roots, nil
|
||||
}
|
||||
+
|
||||
+func verifyCertWithSystem(block *pem.Block, add func(*Certificate)) {
|
||||
+ data := pem.EncodeToMemory(block)
|
||||
+ var cmd *exec.Cmd
|
||||
+ if needsTmpFiles() {
|
||||
+ f, err := ioutil.TempFile("", "cert")
|
||||
+ if err != nil {
|
||||
+ fmt.Fprintf(os.Stderr, "can't create temporary file for cert: %v", err)
|
||||
+ return
|
||||
+ }
|
||||
+ defer os.Remove(f.Name())
|
||||
+ if _, err := f.Write(data); err != nil {
|
||||
+ fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
|
||||
+ return
|
||||
+ }
|
||||
+ if err := f.Close(); err != nil {
|
||||
+ fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
|
||||
+ return
|
||||
+ }
|
||||
+ cmd = exec.Command("/usr/bin/security", "verify-cert", "-c", f.Name(), "-l")
|
||||
+ } else {
|
||||
+ cmd = exec.Command("/usr/bin/security", "verify-cert", "-c", "/dev/stdin", "-l")
|
||||
+ cmd.Stdin = bytes.NewReader(data)
|
||||
+ }
|
||||
+ if cmd.Run() == nil {
|
||||
+ // Non-zero exit means untrusted
|
||||
+ cert, err := ParseCertificate(block.Bytes)
|
||||
+ if err != nil {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ add(cert)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+var versionCache struct {
|
||||
+ sync.Once
|
||||
+ major int
|
||||
+}
|
||||
+
|
||||
+// needsTmpFiles reports whether the OS is <= 10.11 (which requires real
|
||||
+// files as arguments to the security command).
|
||||
+func needsTmpFiles() bool {
|
||||
+ versionCache.Do(func() {
|
||||
+ release, err := syscall.Sysctl("kern.osrelease")
|
||||
+ if err != nil {
|
||||
+ return
|
||||
+ }
|
||||
+ for i, c := range release {
|
||||
+ if c == '.' {
|
||||
+ release = release[:i]
|
||||
+ break
|
||||
+ }
|
||||
+ }
|
||||
+ major, err := strconv.Atoi(release)
|
||||
+ if err != nil {
|
||||
+ return
|
||||
+ }
|
||||
+ versionCache.major = major
|
||||
+ })
|
||||
+ return versionCache.major <= 15
|
||||
+}
|
||||
diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go
|
||||
index cc6d23c..38f314b 100644
|
||||
--- a/src/crypto/x509/root_darwin_test.go
|
||||
+++ b/src/crypto/x509/root_darwin_test.go
|
||||
@@ -29,6 +29,7 @@ func TestSystemRoots(t *testing.T) {
|
||||
// On Mavericks, there are 212 bundled certs; require only
|
||||
// 150 here, since this is just a sanity check, and the
|
||||
// exact number will vary over time.
|
||||
+ t.Logf("got %d roots", len(tt.certs))
|
||||
if want, have := 150, len(tt.certs); have < want {
|
||||
t.Fatalf("want at least %d system roots, have %d", want, have)
|
||||
}
|
||||
--
|
||||
2.5.5
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +0,0 @@
|
|||
# there are ELF files in src which are testdata and shouldn't be modified
|
||||
-b /usr/lib/golang/src
|
||||
-b /usr/lib64/golang/src
|
58
golang.spec
58
golang.spec
|
@ -48,7 +48,7 @@
|
|||
# make check not to fail due to it
|
||||
|
||||
# Controls what ever we fails on failed tests
|
||||
%ifarch %{golang_arches}
|
||||
%ifarch x86_64 %{ix86} aarch64
|
||||
%global fail_on_tests 1
|
||||
%else
|
||||
%global fail_on_tests 0
|
||||
|
@ -85,11 +85,11 @@
|
|||
%endif
|
||||
|
||||
%global go_api 1.5
|
||||
%global go_version 1.5.3
|
||||
%global go_version 1.5.4
|
||||
|
||||
Name: golang
|
||||
Version: 1.5.3
|
||||
Release: 1%{?dist}
|
||||
Version: 1.5.4
|
||||
Release: 5%{?dist}
|
||||
Summary: The Go Programming Language
|
||||
# source tree includes several copies of Mark.Twain-Tom.Sawyer.txt under Public Domain
|
||||
License: BSD and Public Domain
|
||||
|
@ -120,12 +120,11 @@ Requires: go-srpm-macros
|
|||
|
||||
Patch0: golang-1.2-verbose-build.patch
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1038683
|
||||
Patch1: golang-1.2-remove-ECC-p224.patch
|
||||
# Accept x509 certs with negative serial
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1290543
|
||||
# https://github.com/golang/go/issues/8265
|
||||
Patch2: bz1290543.patch
|
||||
Patch3: CVE-2016-5386.patch
|
||||
|
||||
# use the arch dependent path in the bootstrap
|
||||
Patch212: golang-1.5-bootstrap-binary-path.patch
|
||||
|
@ -145,6 +144,10 @@ Patch215: ./go1.5-zoneinfo_testing_only.patch
|
|||
# https://bugzilla.redhat.com/show_bug.cgi?id=1271709
|
||||
Patch216: ./golang-1.5.1-a3156aaa12.patch
|
||||
|
||||
# Backpor security fixes from 1.6.4
|
||||
Patch217: httpmultipart.patch
|
||||
Patch218: darwinx509trust.patch
|
||||
|
||||
# Having documentation separate was broken
|
||||
Obsoletes: %{name}-docs < 1.1-4
|
||||
|
||||
|
@ -159,7 +162,6 @@ Obsoletes: emacs-%{name} < 1.4
|
|||
ExclusiveArch: %{golang_arches}
|
||||
|
||||
Source100: golang-gdbinit
|
||||
Source101: golang-prelink.conf
|
||||
|
||||
%description
|
||||
%{summary}.
|
||||
|
@ -223,6 +225,9 @@ Obsoletes: %{name}-pkg-netbsd-arm < 1.4.99
|
|||
Obsoletes: %{name}-pkg-openbsd-386 < 1.4.99
|
||||
Obsoletes: %{name}-pkg-openbsd-amd64 < 1.4.99
|
||||
|
||||
Obsoletes: golang-vet < 0-12.1
|
||||
Obsoletes: golang-cover < 0-12.1
|
||||
|
||||
Requires(post): %{_sbindir}/update-alternatives
|
||||
Requires(postun): %{_sbindir}/update-alternatives
|
||||
|
||||
|
@ -257,11 +262,10 @@ Summary: Golang shared object libraries
|
|||
# increase verbosity of build
|
||||
%patch0 -p1
|
||||
|
||||
# remove the P224 curve
|
||||
%patch1 -p1
|
||||
|
||||
%patch2 -p1
|
||||
|
||||
%patch3 -p1 -b .httpoxy
|
||||
|
||||
# use the arch dependent path in the bootstrap
|
||||
%patch212 -p1
|
||||
|
||||
|
@ -275,6 +279,9 @@ Summary: Golang shared object libraries
|
|||
|
||||
%patch216 -p1
|
||||
|
||||
%patch217 -p1
|
||||
%patch218 -p1
|
||||
|
||||
cp %{SOURCE1} "$(pwd)/src/compress/bzip2/testdata/Mark.Twain-Tom.Sawyer.txt.bz2"
|
||||
|
||||
%build
|
||||
|
@ -397,11 +404,6 @@ ln -sf /etc/alternatives/gofmt $RPM_BUILD_ROOT%{_bindir}/gofmt
|
|||
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/gdbinit.d
|
||||
cp -av %{SOURCE100} $RPM_BUILD_ROOT%{_sysconfdir}/gdbinit.d/golang.gdb
|
||||
|
||||
# prelink blacklist
|
||||
mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/prelink.conf.d
|
||||
cp -av %{SOURCE101} $RPM_BUILD_ROOT%{_sysconfdir}/prelink.conf.d/golang.conf
|
||||
|
||||
|
||||
%check
|
||||
export GOROOT=$(pwd -P)
|
||||
export PATH="$GOROOT"/bin:"$PATH"
|
||||
|
@ -416,6 +418,10 @@ export GO_LDFLAGS="-linkmode internal"
|
|||
%if !%{cgo_enabled} || !%{external_linker}
|
||||
export CGO_ENABLED=0
|
||||
%endif
|
||||
|
||||
# make sure to not timeout
|
||||
export GO_TEST_TIMEOUT_SCALE=2
|
||||
|
||||
%if %{fail_on_tests}
|
||||
./run.bash --no-rebuild -v -v -v -k
|
||||
%else
|
||||
|
@ -465,9 +471,6 @@ fi
|
|||
# gdbinit (for gdb debugging)
|
||||
%{_sysconfdir}/gdbinit.d
|
||||
|
||||
# prelink blacklist
|
||||
%{_sysconfdir}/prelink.conf.d
|
||||
|
||||
%files -f go-src.list src
|
||||
|
||||
%files -f go-docs.list docs
|
||||
|
@ -485,6 +488,25 @@ fi
|
|||
%endif
|
||||
|
||||
%changelog
|
||||
* Tue Dec 06 2016 Jakub Čajka <jcajka@redhat.com> - 1.5.4-5
|
||||
- Resolves: BZ#1401987
|
||||
|
||||
* Fri Nov 18 2016 Jakub Čajka <jcajka@redhat.com> - 1.5.4-4
|
||||
- re-enable p224 curve (see BZ#1038683)
|
||||
|
||||
* Mon Aug 08 2016 Jakub Čajka <jcajka@redhat.com> - 1.5.4-3
|
||||
-Obsolete golang-vet and golang-cover from golang-googlecode-tools package
|
||||
vet/cover binaries are provided by golang-bin rpm(thanks to jchaloup)
|
||||
- resolves: #1268206
|
||||
|
||||
* Tue Jul 19 2016 Jakub Čajka <jcajka@redhat.com> - 1.5.4-2
|
||||
- Resolves: bz1357602 - CVE-2016-5386
|
||||
|
||||
* Wed Apr 13 2016 Jakub Čajka <jcajka@redhat.com> - 1.5.4-1
|
||||
- rebase to 1.5.4
|
||||
- resolves bz1324344 - CVE-2016-3959
|
||||
- resolves bz1324951 - prelink is gone, /etc/prelink.conf.d/* is no longer used
|
||||
|
||||
* Thu Jan 14 2016 Jakub Čajka <jcajka@redhat.com> - 1.5.3-1
|
||||
- rebase to 1.5.3
|
||||
- resolves bz1293451, CVE-2015-8618
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
From f0fa13b346c1be50aae0eb4349a7c09bdc5826fc Mon Sep 17 00:00:00 2001
|
||||
From: Michael Fraenkel <michael.fraenkel@gmail.com>
|
||||
Date: Wed, 5 Oct 2016 11:27:34 -0400
|
||||
Subject: [PATCH 1/4] [release-branch.go1.6] net/http: multipart ReadForm close
|
||||
file after copy
|
||||
|
||||
Always close the file regardless of whether the copy succeeds or fails.
|
||||
Pass along the close error if the copy succeeds
|
||||
|
||||
Updates #16296
|
||||
|
||||
Change-Id: Ib394655b91d25750f029f17b3846d985f673fb50
|
||||
Reviewed-on: https://go-review.googlesource.com/30410
|
||||
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
|
||||
TryBot-Result: Gobot Gobot <gobot@golang.org>
|
||||
Reviewed-on: https://go-review.googlesource.com/33640
|
||||
Reviewed-by: Chris Broadfoot <cbro@golang.org>
|
||||
---
|
||||
src/mime/multipart/formdata.go | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
|
||||
index eee53fc..806b460 100644
|
||||
--- a/src/mime/multipart/formdata.go
|
||||
+++ b/src/mime/multipart/formdata.go
|
||||
@@ -75,8 +75,10 @@ func (r *Reader) ReadForm(maxMemory int64) (f *Form, err error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
- defer file.Close()
|
||||
_, err = io.Copy(file, io.MultiReader(&b, p))
|
||||
+ if cerr := file.Close(); err == nil {
|
||||
+ err = cerr
|
||||
+ }
|
||||
if err != nil {
|
||||
os.Remove(file.Name())
|
||||
return nil, err
|
||||
--
|
||||
2.5.5
|
||||
|
Loading…
Reference in New Issue