[Pkg-golang-commits] [golang] 02/03: New upstream version 1.7.4

Tianon Gravi tianon at debian.org
Fri Dec 2 00:10:18 UTC 2016


This is an automated email from the git hooks/post-receive script.

tianon pushed a commit to branch golang-1.7
in repository golang.

commit de85607dbaa69b32855648c1f11616b69746cf88
Author: Tianon Gravi <tianon at debian.org>
Date:   Thu Dec 1 16:09:07 2016 -0800

    New upstream version 1.7.4
---
 VERSION                             |   2 +-
 doc/devel/release.html              |  15 ++++-
 doc/go1.7.html                      |   3 +-
 doc/install-source.html             |  41 ++++++++-----
 src/crypto/x509/cert_pool.go        |  15 +++++
 src/crypto/x509/root_cgo_darwin.go  |  81 ++++++++++++++++++++++---
 src/crypto/x509/root_darwin.go      | 114 +++++++++++++++++++++++++++++++++++-
 src/crypto/x509/root_darwin_test.go |   1 +
 src/mime/multipart/formdata.go      |   4 +-
 9 files changed, 246 insertions(+), 30 deletions(-)

diff --git a/VERSION b/VERSION
index 816aead..83caa74 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.7.3
\ No newline at end of file
+go1.7.4
\ No newline at end of file
diff --git a/doc/devel/release.html b/doc/devel/release.html
index 9a4daf1..51957df 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -63,6 +63,12 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.3">Go
 1.7.3 milestone</a> on our issue tracker for details.
 </p>
 
+<p>
+go1.7.4 (released 2016/12/01) includes two security fixes.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
+1.7.4 milestone</a> on our issue tracker for details.
+</p>
+
 <h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
 
 <p>
@@ -89,11 +95,18 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.2">Go
 <p>
 go1.6.3 (released 2016/07/17) includes security fixes to the
 <code>net/http/cgi</code> package and <code>net/http</code> package when used in
-a CGI environment. This release also adds support for macOS Sierra.
+a CGI environment.
 See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.3">Go
 1.6.3 milestone</a> on our issue tracker for details.
 </p>
 
+<p>
+go1.6.4 (released 2016/12/01) includes two security fixes.
+It contains the same fixes as Go 1.7.4 and was released at the same time.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
+1.7.4 milestone</a> on our issue tracker for details.
+</p>
+
 <h2 id="go1.5">go1.5 (released 2015/08/19)</h2>
 
 <p>
diff --git a/doc/go1.7.html b/doc/go1.7.html
index 762c1ec..6839c5e 100644
--- a/doc/go1.7.html
+++ b/doc/go1.7.html
@@ -67,8 +67,7 @@ This change has no effect on the correctness of existing programs.
 
 <p>
 Go 1.7 adds support for macOS 10.12 Sierra.
-This support was backported to Go 1.6.3.
-Binaries built with versions of Go before 1.6.3 will not work
+Binaries built with versions of Go before 1.7 will not work
 correctly on Sierra.
 </p>
 
diff --git a/doc/install-source.html b/doc/install-source.html
index d0a4ed2..77616c1 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -119,27 +119,39 @@ Go does not support CentOS 6 on these systems.
 <p>
 The Go tool chain is written in Go. To build it, you need a Go compiler installed.
 The scripts that do the initial build of the tools look for an existing Go tool
-chain in <code>$HOME/go1.4</code>.
-(This path may be overridden by setting the <code>GOROOT_BOOTSTRAP</code>
-environment variable.)
+chain in <code>$GOROOT_BOOTSTRAP</code>.
+If unset, the default value of <code>GOROOT_BOOTSTRAP</code>
+is <code>$HOME/go1.4</code>.
 </p>
 
 <p>
-Build the tools with Go version 1.4 or a point release (1.4.1, 1.4.2 etc.).
-Go 1.4 binaries can be found at <a href="/dl/">the downloads page</a>.
+There are many options for the bootstrap tool chain.
+After obtaining one, set <code>GOROOT_BOOTSTRAP</code> to the
+directory containing the unpacked tree.
+For example, <code>$GOROOT_BOOTSTRAP/bin/go</code> should be
+the <code>go</code> command binary for the bootstrap tool chain.
 </p>
 
 <p>
-Download the zip or tarball of Go 1.4 for your platform and extract it to
-<code>$HOME/go1.4</code> (or your nominated <code>GOROOT_BOOTSTRAP</code>
-location).
+To use a binary release as a bootstrap tool chain, see
+<a href="/dl/">the downloads page</a> or use any other
+packaged Go distribution.
 </p>
 
 <p>
-If you want to install Go 1.5 on a system that is not supported by Go 1.4 (such
-as <code>linux/ppc64</code> and <code>linux/mips64le</code>) you can either use
-<a href="/src/bootstrap.bash">bootstrap.bash</a> on a system that can bootstrap Go
-1.5 normally, or bootstrap with gccgo 5.
+To build a bootstrap tool chain from source, use
+either the git branch <code>release-branch.go1.4</code> or
+<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20161024.tar.gz">go1.4-bootstrap-20161024.tar.gz</a>,
+which contains the Go 1.4 source code plus accumulated fixes
+to keep the tools running on newer operating systems.
+(Go 1.4 was the last distribution in which the tool chain was written in C.)
+</p>
+
+<p>
+To cross-compile a bootstrap tool chain from source, which is
+necessary on systems Go 1.4 did not target (for
+example, <code>linux/ppc64le</code>), install Go on a different system
+and run <a href="/src/bootstrap.bash">bootstrap.bash</a>.
 </p>
 
 <p>
@@ -158,8 +170,9 @@ and used as <code>GOROOT_BOOTSTRAP</code> to bootstrap a local build.
 </p>
 
 <p>
-To use gccgo, you need to arrange for <code>$GOROOT_BOOTSTRAP/bin/go</code> to be
-the go tool that comes as part of gccgo 5. For example on Ubuntu Vivid:
+To use gccgo as the bootstrap toolchain, you need to arrange
+for <code>$GOROOT_BOOTSTRAP/bin/go</code> to be the go tool that comes
+as part of gccgo 5. For example on Ubuntu Vivid:
 </p>
 
 <pre>
diff --git a/src/crypto/x509/cert_pool.go b/src/crypto/x509/cert_pool.go
index 59ab887..8438bf6 100644
--- a/src/crypto/x509/cert_pool.go
+++ b/src/crypto/x509/cert_pool.go
@@ -64,6 +64,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 a4b33c7..d599174 100644
--- a/src/crypto/x509/root_cgo_darwin.go
+++ b/src/crypto/x509/root_cgo_darwin.go
@@ -73,10 +73,11 @@ int useOldCode() {
 //
 // 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 must be released (using CFRelease) after
-// we've consumed its content.
-int FetchPEMRoots(CFDataRef *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);
 	}
@@ -93,23 +94,69 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
 		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;
-		// Only get certificates from domain that are trusted
 		OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs);
 		if (err != noErr) {
 			continue;
 		}
 
-		int numCerts = CFArrayGetCount(certs);
+		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) {
@@ -138,13 +185,16 @@ int FetchPEMRoots(CFDataRef *pemRoots) {
 			}
 
 			if (data != NULL) {
-				CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
+				CFMutableDataRef appendTo = untrusted ? combinedUntrustedData : combinedData;
+				CFDataAppendBytes(appendTo, CFDataGetBytePtr(data), CFDataGetLength(data));
 				CFRelease(data);
 			}
 		}
 		CFRelease(certs);
 	}
+	CFRelease(policy);
 	*pemRoots = combinedData;
+	*untrustedPemRoots = combinedUntrustedData;
 	return 0;
 }
 */
@@ -158,7 +208,8 @@ func loadSystemRoots() (*CertPool, error) {
 	roots := NewCertPool()
 
 	var data C.CFDataRef = nil
-	err := C.FetchPEMRoots(&data)
+	var untrustedData C.CFDataRef = nil
+	err := C.FetchPEMRoots(&data, &untrustedData)
 	if err == -1 {
 		// TODO: better error message
 		return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo")
@@ -167,5 +218,19 @@ func loadSystemRoots() (*CertPool, error) {
 	defer C.CFRelease(C.CFTypeRef(data))
 	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
 	roots.AppendCertsFromPEM(buf)
-	return roots, nil
+	if untrustedData == nil {
+		return roots, nil
+	}
+	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)
+		}
+	}
+	return trustedRoots, nil
 }
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 8b6b151..c8ca3ea 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)
 		}
diff --git a/src/mime/multipart/formdata.go b/src/mime/multipart/formdata.go
index 8085bd3..c9e3188 100644
--- a/src/mime/multipart/formdata.go
+++ b/src/mime/multipart/formdata.go
@@ -79,8 +79,10 @@ func (r *Reader) readForm(maxMemory int64) (_ *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

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-golang/golang.git



More information about the pkg-golang-commits mailing list