[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#768071: unblock: docker.io/1.3.1~dfsg1-1



retitle 768071 unblock: docker.io/1.3.1~dfsg1-2
thanks

per paultag's instructions (updated debdiff is attached)

♥,
- Tianon
  4096R / B42F 6819 007F 00F8 8E36  4FD4 036A 9C25 BF35 7DD4
diff -Nru docker.io-1.3.0~dfsg1/CHANGELOG.md docker.io-1.3.1~dfsg1/CHANGELOG.md
--- docker.io-1.3.0~dfsg1/CHANGELOG.md	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/CHANGELOG.md	2014-10-30 13:44:46.000000000 +0000
@@ -1,5 +1,23 @@
 # Changelog
 
+## 1.3.1 (2014-10-28)
+
+#### Security
+* Prevent fallback to SSL protocols < TLS 1.0 for client, daemon and registry
++ Secure HTTPS connection to registries with certificate verification and without HTTP fallback unless `--insecure-registry` is specified
+
+#### Runtime
+- Fix issue where volumes would not be shared
+
+#### Client
+- Fix issue with `--iptables=false` not automatically setting `--ip-masq=false`
+- Fix docker run output to non-TTY stdout
+
+#### Builder
+- Fix escaping `$` for environment variables
+- Fix issue with lowercase `onbuild` Dockerfile instruction
+- Restrict envrionment variable expansion to `ENV`, `ADD`, `COPY`, `WORKDIR`, `EXPOSE`, `VOLUME` and `USER`
+
 ## 1.3.0 (2014-10-14)
 
 #### Notable features since 1.2.0
diff -Nru docker.io-1.3.0~dfsg1/VERSION docker.io-1.3.1~dfsg1/VERSION
--- docker.io-1.3.0~dfsg1/VERSION	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/VERSION	2014-10-30 13:44:46.000000000 +0000
@@ -1 +1 @@
-1.3.0
+1.3.1
diff -Nru docker.io-1.3.0~dfsg1/api/client/commands.go docker.io-1.3.1~dfsg1/api/client/commands.go
--- docker.io-1.3.0~dfsg1/api/client/commands.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/api/client/commands.go	2014-10-30 13:44:46.000000000 +0000
@@ -1986,6 +1986,10 @@
 }
 
 func (cli *DockerCli) pullImage(image string) error {
+	return cli.pullImageCustomOut(image, cli.out)
+}
+
+func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
 	v := url.Values{}
 	repos, tag := parsers.ParseRepositoryTag(image)
 	// pull only the image tagged 'latest' if no tag was specified
@@ -2014,7 +2018,7 @@
 	registryAuthHeader := []string{
 		base64.URLEncoding.EncodeToString(buf),
 	}
-	if err = cli.stream("POST", "/images/create?"+v.Encode(), nil, cli.out, map[string][]string{"X-Registry-Auth": registryAuthHeader}); err != nil {
+	if err = cli.stream("POST", "/images/create?"+v.Encode(), nil, out, map[string][]string{"X-Registry-Auth": registryAuthHeader}); err != nil {
 		return err
 	}
 	return nil
@@ -2081,7 +2085,8 @@
 	if statusCode == 404 {
 		fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", config.Image)
 
-		if err = cli.pullImage(config.Image); err != nil {
+		// we don't want to write to stdout anything apart from container.ID
+		if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil {
 			return nil, err
 		}
 		// Retry
diff -Nru docker.io-1.3.0~dfsg1/api/server/server.go docker.io-1.3.1~dfsg1/api/server/server.go
--- docker.io-1.3.0~dfsg1/api/server/server.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/api/server/server.go	2014-10-30 13:44:46.000000000 +0000
@@ -1439,6 +1439,8 @@
 		tlsConfig := &tls.Config{
 			NextProtos:   []string{"http/1.1"},
 			Certificates: []tls.Certificate{cert},
+			// Avoid fallback on insecure SSL protocols
+			MinVersion: tls.VersionTLS10,
 		}
 		if job.GetenvBool("TlsVerify") {
 			certPool := x509.NewCertPool()
diff -Nru docker.io-1.3.0~dfsg1/builder/dispatchers.go docker.io-1.3.1~dfsg1/builder/dispatchers.go
--- docker.io-1.3.0~dfsg1/builder/dispatchers.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/builder/dispatchers.go	2014-10-30 13:44:46.000000000 +0000
@@ -11,6 +11,7 @@
 	"fmt"
 	"io/ioutil"
 	"path/filepath"
+	"regexp"
 	"strings"
 
 	"github.com/docker/docker/nat"
@@ -129,7 +130,7 @@
 		return fmt.Errorf("%s isn't allowed as an ONBUILD trigger", triggerInstruction)
 	}
 
-	original = strings.TrimSpace(strings.TrimLeft(original, "ONBUILD"))
+	original = regexp.MustCompile(`(?i)^\s*ONBUILD\s*`).ReplaceAllString(original, "")
 
 	b.Config.OnBuild = append(b.Config.OnBuild, original)
 	return b.commit("", b.Config.Cmd, fmt.Sprintf("ONBUILD %s", original))
@@ -194,7 +195,7 @@
 
 	defer func(cmd []string) { b.Config.Cmd = cmd }(cmd)
 
-	log.Debugf("Command to be executed: %v", b.Config.Cmd)
+	log.Debugf("[BUILDER] Command to be executed: %v", b.Config.Cmd)
 
 	hit, err := b.probeCache()
 	if err != nil {
@@ -233,7 +234,7 @@
 func cmd(b *Builder, args []string, attributes map[string]bool, original string) error {
 	b.Config.Cmd = handleJsonArgs(args, attributes)
 
-	if !attributes["json"] && len(b.Config.Entrypoint) == 0 {
+	if !attributes["json"] {
 		b.Config.Cmd = append([]string{"/bin/sh", "-c"}, b.Config.Cmd...)
 	}
 
@@ -260,14 +261,14 @@
 	parsed := handleJsonArgs(args, attributes)
 
 	switch {
-	case len(parsed) == 0:
-		// ENTYRPOINT []
-		b.Config.Entrypoint = nil
 	case attributes["json"]:
 		// ENTRYPOINT ["echo", "hi"]
 		b.Config.Entrypoint = parsed
+	case len(parsed) == 0:
+		// ENTRYPOINT []
+		b.Config.Entrypoint = nil
 	default:
-		// ENTYRPOINT echo hi
+		// ENTRYPOINT echo hi
 		b.Config.Entrypoint = []string{"/bin/sh", "-c", parsed[0]}
 	}
 
diff -Nru docker.io-1.3.0~dfsg1/builder/evaluator.go docker.io-1.3.1~dfsg1/builder/evaluator.go
--- docker.io-1.3.0~dfsg1/builder/evaluator.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/builder/evaluator.go	2014-10-30 13:44:46.000000000 +0000
@@ -41,6 +41,17 @@
 	ErrDockerfileEmpty = errors.New("Dockerfile cannot be empty")
 )
 
+// Environment variable interpolation will happen on these statements only.
+var replaceEnvAllowed = map[string]struct{}{
+	"env":     {},
+	"add":     {},
+	"copy":    {},
+	"workdir": {},
+	"expose":  {},
+	"volume":  {},
+	"user":    {},
+}
+
 var evaluateTable map[string]func(*Builder, []string, map[string]bool, string) error
 
 func init() {
@@ -149,7 +160,7 @@
 	b.dockerfile = ast
 
 	// some initializations that would not have been supplied by the caller.
-	b.Config = &runconfig.Config{Entrypoint: []string{}, Cmd: nil}
+	b.Config = &runconfig.Config{}
 	b.TmpContainers = map[string]struct{}{}
 
 	for i, n := range b.dockerfile.Children {
@@ -196,13 +207,18 @@
 
 	if cmd == "onbuild" {
 		ast = ast.Next.Children[0]
-		strs = append(strs, b.replaceEnv(ast.Value))
+		strs = append(strs, ast.Value)
 		msg += " " + ast.Value
 	}
 
 	for ast.Next != nil {
 		ast = ast.Next
-		strs = append(strs, b.replaceEnv(ast.Value))
+		var str string
+		str = ast.Value
+		if _, ok := replaceEnvAllowed[cmd]; ok {
+			str = b.replaceEnv(ast.Value)
+		}
+		strs = append(strs, str)
 		msg += " " + ast.Value
 	}
 
diff -Nru docker.io-1.3.0~dfsg1/builder/parser/parser.go docker.io-1.3.1~dfsg1/builder/parser/parser.go
--- docker.io-1.3.0~dfsg1/builder/parser/parser.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/builder/parser/parser.go	2014-10-30 13:44:46.000000000 +0000
@@ -87,10 +87,11 @@
 
 	if sexp.Value != "" || sexp.Next != nil || sexp.Children != nil {
 		node.Next = sexp
-		node.Attributes = attrs
-		node.Original = line
 	}
 
+	node.Attributes = attrs
+	node.Original = line
+
 	return "", node, nil
 }
 
diff -Nru docker.io-1.3.0~dfsg1/builder/support.go docker.io-1.3.1~dfsg1/builder/support.go
--- docker.io-1.3.0~dfsg1/builder/support.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/builder/support.go	2014-10-30 13:44:46.000000000 +0000
@@ -10,13 +10,26 @@
 	// `\$` - match literal $
 	// `[[:alnum:]_]+` - match things like `$SOME_VAR`
 	// `{[[:alnum:]_]+}` - match things like `${SOME_VAR}`
-	tokenEnvInterpolation = regexp.MustCompile(`(\\\\+|[^\\]|\b|\A)\$([[:alnum:]_]+|{[[:alnum:]_]+})`)
+	tokenEnvInterpolation = regexp.MustCompile(`(\\|\\\\+|[^\\]|\b|\A)\$([[:alnum:]_]+|{[[:alnum:]_]+})`)
 	// this intentionally punts on more exotic interpolations like ${SOME_VAR%suffix} and lets the shell handle those directly
 )
 
 // handle environment replacement. Used in dispatcher.
 func (b *Builder) replaceEnv(str string) string {
 	for _, match := range tokenEnvInterpolation.FindAllString(str, -1) {
+		idx := strings.Index(match, "\\$")
+		if idx != -1 {
+			if idx+2 >= len(match) {
+				str = strings.Replace(str, match, "\\$", -1)
+				continue
+			}
+
+			prefix := match[:idx]
+			stripped := match[idx+2:]
+			str = strings.Replace(str, match, prefix+"$"+stripped, -1)
+			continue
+		}
+
 		match = match[strings.Index(match, "$"):]
 		matchKey := strings.Trim(match, "${}")
 
diff -Nru docker.io-1.3.0~dfsg1/builtins/builtins.go docker.io-1.3.1~dfsg1/builtins/builtins.go
--- docker.io-1.3.0~dfsg1/builtins/builtins.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/builtins/builtins.go	2014-10-30 13:44:46.000000000 +0000
@@ -10,7 +10,6 @@
 	"github.com/docker/docker/engine"
 	"github.com/docker/docker/events"
 	"github.com/docker/docker/pkg/parsers/kernel"
-	"github.com/docker/docker/registry"
 )
 
 func Register(eng *engine.Engine) error {
@@ -26,7 +25,8 @@
 	if err := eng.Register("version", dockerVersion); err != nil {
 		return err
 	}
-	return registry.NewService().Install(eng)
+
+	return nil
 }
 
 // remote: a RESTful api for cross-docker communication
diff -Nru docker.io-1.3.0~dfsg1/daemon/config.go docker.io-1.3.1~dfsg1/daemon/config.go
--- docker.io-1.3.0~dfsg1/daemon/config.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/daemon/config.go	2014-10-30 13:44:46.000000000 +0000
@@ -31,6 +31,7 @@
 	BridgeIface                 string
 	BridgeIP                    string
 	FixedCIDR                   string
+	InsecureRegistries          []string
 	InterContainerCommunication bool
 	GraphDriver                 string
 	GraphOptions                []string
@@ -55,6 +56,7 @@
 	flag.StringVar(&config.BridgeIP, []string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
 	flag.StringVar(&config.BridgeIface, []string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge\nuse 'none' to disable container networking")
 	flag.StringVar(&config.FixedCIDR, []string{"-fixed-cidr"}, "", "IPv4 subnet for fixed IPs (ex: 10.20.0.0/16)\nthis subnet must be nested in the bridge subnet (which is defined by -b or --bip)")
+	opts.ListVar(&config.InsecureRegistries, []string{"-insecure-registry"}, "Enable insecure communication with specified registries (no certificate verification for HTTPS and enable HTTP fallback)")
 	flag.BoolVar(&config.InterContainerCommunication, []string{"#icc", "-icc"}, true, "Enable inter-container communication")
 	flag.StringVar(&config.GraphDriver, []string{"s", "-storage-driver"}, "", "Force the Docker runtime to use a specific storage driver")
 	flag.StringVar(&config.ExecDriver, []string{"e", "-exec-driver"}, "native", "Force the Docker runtime to use a specific exec driver")
diff -Nru docker.io-1.3.0~dfsg1/daemon/daemon.go docker.io-1.3.1~dfsg1/daemon/daemon.go
--- docker.io-1.3.0~dfsg1/daemon/daemon.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/daemon/daemon.go	2014-10-30 13:44:46.000000000 +0000
@@ -731,7 +731,7 @@
 		return nil, fmt.Errorf("You specified --iptables=false with --icc=false. ICC uses iptables to function. Please set --icc or --iptables to true.")
 	}
 	if !config.EnableIptables && config.EnableIpMasq {
-		return nil, fmt.Errorf("You specified --iptables=false with --ipmasq=true. IP masquerading uses iptables to function. Please set --ipmasq to false or --iptables to true.")
+		config.EnableIpMasq = false
 	}
 	config.DisableNetwork = config.BridgeIface == disableNetworkBridge
 
@@ -831,7 +831,7 @@
 	}
 
 	log.Debugf("Creating repository list")
-	repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, config.Mirrors)
+	repositories, err := graph.NewTagStore(path.Join(config.Root, "repositories-"+driver.String()), g, config.Mirrors, config.InsecureRegistries)
 	if err != nil {
 		return nil, fmt.Errorf("Couldn't create Tag store: %s", err)
 	}
diff -Nru docker.io-1.3.0~dfsg1/daemon/volumes.go docker.io-1.3.1~dfsg1/daemon/volumes.go
--- docker.io-1.3.0~dfsg1/daemon/volumes.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/daemon/volumes.go	2014-10-30 13:44:46.000000000 +0000
@@ -133,6 +133,7 @@
 	// Get the rest of the volumes
 	for path := range container.Config.Volumes {
 		// Check if this is already added as a bind-mount
+		path = filepath.Clean(path)
 		if _, exists := mounts[path]; exists {
 			continue
 		}
@@ -182,6 +183,8 @@
 		return "", "", false, fmt.Errorf("cannot bind mount volume: %s volume paths must be absolute.", path)
 	}
 
+	path = filepath.Clean(path)
+	mountToPath = filepath.Clean(mountToPath)
 	return path, mountToPath, writable, nil
 }
 
diff -Nru docker.io-1.3.0~dfsg1/debian/changelog docker.io-1.3.1~dfsg1/debian/changelog
--- docker.io-1.3.0~dfsg1/debian/changelog	2014-10-17 06:56:10.000000000 +0000
+++ docker.io-1.3.1~dfsg1/debian/changelog	2014-11-07 20:11:37.000000000 +0000
@@ -1,3 +1,19 @@
+docker.io (1.3.1~dfsg1-2) unstable; urgency=medium
+
+  * Remove deprecated /usr/bin/docker.io symlink
+    - added as a temporary shim in 1.0.0~dfsg1-1 (13 Jun 2014)
+    - unused by package-installed files in 1.2.0~dfsg1-1 (13 Sep 2014)
+
+ -- Tianon Gravi <admwiggin@gmail.com>  Fri, 07 Nov 2014 13:11:34 -0700
+
+docker.io (1.3.1~dfsg1-1) unstable; urgency=high
+
+  * Update to 1.3.1 upstream release
+    - fix for CVE-2014-5277
+    - https://groups.google.com/d/topic/docker-user/oYm0i3xShJU/discussion
+
+ -- Tianon Gravi <admwiggin@gmail.com>  Mon, 03 Nov 2014 08:26:29 -0700
+
 docker.io (1.3.0~dfsg1-1) unstable; urgency=medium
 
   * Updated to 1.3.0 upstream release.
diff -Nru docker.io-1.3.0~dfsg1/debian/rules docker.io-1.3.1~dfsg1/debian/rules
--- docker.io-1.3.0~dfsg1/debian/rules	2014-10-17 06:36:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/debian/rules	2014-11-07 20:11:30.000000000 +0000
@@ -54,8 +54,6 @@
 	# install docker binary
 	mkdir -p debian/docker.io/usr/bin
 	mv bundles/${DOCKER_VERSION}/dynbinary/docker-${DOCKER_VERSION} debian/docker.io/usr/bin/docker
-	# install docker.io symlink for easier transition
-	ln -s docker debian/docker.io/usr/bin/docker.io
 	
 	# install dockerinit binary
 	mkdir -p debian/docker.io/${INITDIR}
diff -Nru docker.io-1.3.0~dfsg1/debian/upstream-version-gitcommits docker.io-1.3.1~dfsg1/debian/upstream-version-gitcommits
--- docker.io-1.3.0~dfsg1/debian/upstream-version-gitcommits	2014-10-17 06:34:38.000000000 +0000
+++ docker.io-1.3.1~dfsg1/debian/upstream-version-gitcommits	2014-10-31 21:26:53.000000000 +0000
@@ -33,3 +33,4 @@
 1.1.2: d84a070
 1.2.0: fa7b24f
 1.3.0: c78088f
+1.3.1: 4e9bbfa
diff -Nru docker.io-1.3.0~dfsg1/docker/daemon.go docker.io-1.3.1~dfsg1/docker/daemon.go
--- docker.io-1.3.0~dfsg1/docker/daemon.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/docker/daemon.go	2014-10-30 13:44:46.000000000 +0000
@@ -14,6 +14,7 @@
 	"github.com/docker/docker/engine"
 	flag "github.com/docker/docker/pkg/mflag"
 	"github.com/docker/docker/pkg/signal"
+	"github.com/docker/docker/registry"
 )
 
 const CanDaemon = true
@@ -33,11 +34,17 @@
 	}
 	eng := engine.New()
 	signal.Trap(eng.Shutdown)
+
 	// Load builtins
 	if err := builtins.Register(eng); err != nil {
 		log.Fatal(err)
 	}
 
+	// load registry service
+	if err := registry.NewService(daemonCfg.InsecureRegistries).Install(eng); err != nil {
+		log.Fatal(err)
+	}
+
 	// load the daemon in the background so we can immediately start
 	// the http api so that connections don't fail while the daemon
 	// is booting
diff -Nru docker.io-1.3.0~dfsg1/docker/docker.go docker.io-1.3.1~dfsg1/docker/docker.go
--- docker.io-1.3.0~dfsg1/docker/docker.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/docker/docker.go	2014-10-30 13:44:46.000000000 +0000
@@ -93,6 +93,8 @@
 			}
 			tlsConfig.Certificates = []tls.Certificate{cert}
 		}
+		// Avoid fallback to SSL protocols < TLS1.0
+		tlsConfig.MinVersion = tls.VersionTLS10
 	}
 
 	if *flTls || *flTlsVerify {
diff -Nru docker.io-1.3.0~dfsg1/docs/mkdocs.yml docker.io-1.3.1~dfsg1/docs/mkdocs.yml
--- docker.io-1.3.0~dfsg1/docs/mkdocs.yml	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/docs/mkdocs.yml	2014-10-30 13:44:46.000000000 +0000
@@ -26,6 +26,7 @@
 
 # Introduction:
 - ['index.md', 'About', 'Docker']
+- ['release-notes.md', 'About', 'Release Notes']
 - ['introduction/index.md', '**HIDDEN**']
 - ['introduction/understanding-docker.md', 'About', 'Understanding Docker']
 
diff -Nru docker.io-1.3.0~dfsg1/graph/pull.go docker.io-1.3.1~dfsg1/graph/pull.go
--- docker.io-1.3.0~dfsg1/graph/pull.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/graph/pull.go	2014-10-30 13:44:46.000000000 +0000
@@ -113,7 +113,9 @@
 		return job.Error(err)
 	}
 
-	endpoint, err := registry.NewEndpoint(hostname)
+	secure := registry.IsSecure(hostname, s.insecureRegistries)
+
+	endpoint, err := registry.NewEndpoint(hostname, secure)
 	if err != nil {
 		return job.Error(err)
 	}
diff -Nru docker.io-1.3.0~dfsg1/graph/push.go docker.io-1.3.1~dfsg1/graph/push.go
--- docker.io-1.3.0~dfsg1/graph/push.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/graph/push.go	2014-10-30 13:44:46.000000000 +0000
@@ -214,7 +214,9 @@
 		return job.Error(err)
 	}
 
-	endpoint, err := registry.NewEndpoint(hostname)
+	secure := registry.IsSecure(hostname, s.insecureRegistries)
+
+	endpoint, err := registry.NewEndpoint(hostname, secure)
 	if err != nil {
 		return job.Error(err)
 	}
diff -Nru docker.io-1.3.0~dfsg1/graph/tags.go docker.io-1.3.1~dfsg1/graph/tags.go
--- docker.io-1.3.0~dfsg1/graph/tags.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/graph/tags.go	2014-10-30 13:44:46.000000000 +0000
@@ -23,10 +23,11 @@
 )
 
 type TagStore struct {
-	path         string
-	graph        *Graph
-	mirrors      []string
-	Repositories map[string]Repository
+	path               string
+	graph              *Graph
+	mirrors            []string
+	insecureRegistries []string
+	Repositories       map[string]Repository
 	sync.Mutex
 	// FIXME: move push/pull-related fields
 	// to a helper type
@@ -54,18 +55,20 @@
 	return true
 }
 
-func NewTagStore(path string, graph *Graph, mirrors []string) (*TagStore, error) {
+func NewTagStore(path string, graph *Graph, mirrors []string, insecureRegistries []string) (*TagStore, error) {
 	abspath, err := filepath.Abs(path)
 	if err != nil {
 		return nil, err
 	}
+
 	store := &TagStore{
-		path:         abspath,
-		graph:        graph,
-		mirrors:      mirrors,
-		Repositories: make(map[string]Repository),
-		pullingPool:  make(map[string]chan struct{}),
-		pushingPool:  make(map[string]chan struct{}),
+		path:               abspath,
+		graph:              graph,
+		mirrors:            mirrors,
+		insecureRegistries: insecureRegistries,
+		Repositories:       make(map[string]Repository),
+		pullingPool:        make(map[string]chan struct{}),
+		pushingPool:        make(map[string]chan struct{}),
 	}
 	// Load the json file if it exists, otherwise create it.
 	if err := store.reload(); os.IsNotExist(err) {
diff -Nru docker.io-1.3.0~dfsg1/graph/tags_unit_test.go docker.io-1.3.1~dfsg1/graph/tags_unit_test.go
--- docker.io-1.3.0~dfsg1/graph/tags_unit_test.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/graph/tags_unit_test.go	2014-10-30 13:44:46.000000000 +0000
@@ -53,7 +53,7 @@
 	if err != nil {
 		t.Fatal(err)
 	}
-	store, err := NewTagStore(path.Join(root, "tags"), graph, nil)
+	store, err := NewTagStore(path.Join(root, "tags"), graph, nil, nil)
 	if err != nil {
 		t.Fatal(err)
 	}
diff -Nru docker.io-1.3.0~dfsg1/hack/release.sh docker.io-1.3.1~dfsg1/hack/release.sh
--- docker.io-1.3.0~dfsg1/hack/release.sh	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/hack/release.sh	2014-10-30 13:44:46.000000000 +0000
@@ -270,7 +270,7 @@
 	done
 
 	# Upload keys
-	s3cmd sync /.gnupg/ s3://$BUCKET/ubuntu/.gnupg/
+	s3cmd sync $HOME/.gnupg/ s3://$BUCKET/ubuntu/.gnupg/
 	gpg --armor --export releasedocker > bundles/$VERSION/ubuntu/gpg
 	s3cmd --acl-public put bundles/$VERSION/ubuntu/gpg s3://$BUCKET/gpg
 
@@ -355,8 +355,8 @@
 
 setup_gpg() {
 	# Make sure that we have our keys
-	mkdir -p /.gnupg/
-	s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ /.gnupg/ || true
+	mkdir -p $HOME/.gnupg/
+	s3cmd sync s3://$BUCKET/ubuntu/.gnupg/ $HOME/.gnupg/ || true
 	gpg --list-keys releasedocker >/dev/null || {
 		gpg --gen-key --batch <<EOF
 Key-Type: RSA
diff -Nru docker.io-1.3.0~dfsg1/integration-cli/docker_cli_build_test.go docker.io-1.3.1~dfsg1/integration-cli/docker_cli_build_test.go
--- docker.io-1.3.0~dfsg1/integration-cli/docker_cli_build_test.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/integration-cli/docker_cli_build_test.go	2014-10-30 13:44:46.000000000 +0000
@@ -2,6 +2,7 @@
 
 import (
 	"archive/tar"
+	"encoding/json"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -15,6 +16,396 @@
 	"github.com/docker/docker/pkg/archive"
 )
 
+func TestBuildShCmdJSONEntrypoint(t *testing.T) {
+	name := "testbuildshcmdjsonentrypoint"
+	defer deleteImages(name)
+
+	_, err := buildImage(
+		name,
+		`
+    FROM busybox
+    ENTRYPOINT ["/bin/echo"]
+    CMD echo test
+    `,
+		true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	out, _, err := runCommandWithOutput(
+		exec.Command(
+			dockerBinary,
+			"run",
+			name))
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if strings.TrimSpace(out) != "/bin/sh -c echo test" {
+		t.Fatal("CMD did not contain /bin/sh -c")
+	}
+
+	logDone("build - CMD should always contain /bin/sh -c when specified without JSON")
+}
+
+func TestBuildEnvironmentReplacementUser(t *testing.T) {
+	name := "testbuildenvironmentreplacement"
+	defer deleteImages(name)
+
+	_, err := buildImage(name, `
+  FROM scratch
+  ENV user foo
+  USER ${user}
+  `, true)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err := inspectFieldJSON(name, "Config.User")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if res != `"foo"` {
+		t.Fatal("User foo from environment not in Config.User on image")
+	}
+
+	logDone("build - user environment replacement")
+}
+
+func TestBuildEnvironmentReplacementVolume(t *testing.T) {
+	name := "testbuildenvironmentreplacement"
+	defer deleteImages(name)
+
+	_, err := buildImage(name, `
+  FROM scratch
+  ENV volume /quux
+  VOLUME ${volume}
+  `, true)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err := inspectFieldJSON(name, "Config.Volumes")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var volumes map[string]interface{}
+
+	if err := json.Unmarshal([]byte(res), &volumes); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, ok := volumes["/quux"]; !ok {
+		t.Fatal("Volume /quux from environment not in Config.Volumes on image")
+	}
+
+	logDone("build - volume environment replacement")
+}
+
+func TestBuildEnvironmentReplacementExpose(t *testing.T) {
+	name := "testbuildenvironmentreplacement"
+	defer deleteImages(name)
+
+	_, err := buildImage(name, `
+  FROM scratch
+  ENV port 80
+  EXPOSE ${port}
+  `, true)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err := inspectFieldJSON(name, "Config.ExposedPorts")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var exposedPorts map[string]interface{}
+
+	if err := json.Unmarshal([]byte(res), &exposedPorts); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, ok := exposedPorts["80/tcp"]; !ok {
+		t.Fatal("Exposed port 80 from environment not in Config.ExposedPorts on image")
+	}
+
+	logDone("build - expose environment replacement")
+}
+
+func TestBuildEnvironmentReplacementWorkdir(t *testing.T) {
+	name := "testbuildenvironmentreplacement"
+	defer deleteImages(name)
+
+	_, err := buildImage(name, `
+  FROM busybox
+  ENV MYWORKDIR /work
+  RUN mkdir ${MYWORKDIR}
+  WORKDIR ${MYWORKDIR}
+  `, true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	logDone("build - workdir environment replacement")
+}
+
+func TestBuildEnvironmentReplacementAddCopy(t *testing.T) {
+	name := "testbuildenvironmentreplacement"
+	defer deleteImages(name)
+
+	ctx, err := fakeContext(`
+  FROM scratch
+  ENV baz foo
+  ENV quux bar
+  ENV dot .
+
+  ADD ${baz} ${dot}
+  COPY ${quux} ${dot}
+  `,
+		map[string]string{
+			"foo": "test1",
+			"bar": "test2",
+		})
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if _, err := buildImageFromContext(name, ctx, true); err != nil {
+		t.Fatal(err)
+	}
+
+	logDone("build - add/copy environment replacement")
+}
+
+func TestBuildEnvironmentReplacementEnv(t *testing.T) {
+	name := "testbuildenvironmentreplacement"
+
+	defer deleteImages(name)
+
+	_, err := buildImage(name,
+		`
+  FROM scratch
+  ENV foo foo
+  ENV bar ${foo}
+  `, true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err := inspectFieldJSON(name, "Config.Env")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	envResult := []string{}
+
+	if err = unmarshalJSON([]byte(res), &envResult); err != nil {
+		t.Fatal(err)
+	}
+
+	found := false
+
+	for _, env := range envResult {
+		parts := strings.SplitN(env, "=", 2)
+		if parts[0] == "bar" {
+			found = true
+			if parts[1] != "foo" {
+				t.Fatal("Could not find replaced var for env `bar`: got %q instead of `foo`", parts[1])
+			}
+		}
+	}
+
+	if !found {
+		t.Fatal("Never found the `bar` env variable")
+	}
+
+	logDone("build - env environment replacement")
+}
+
+func TestBuildHandleEscapes(t *testing.T) {
+	name := "testbuildhandleescapes"
+
+	defer deleteImages(name)
+
+	_, err := buildImage(name,
+		`
+  FROM scratch
+  ENV FOO bar
+  VOLUME ${FOO}
+  `, true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	var result map[string]map[string]struct{}
+
+	res, err := inspectFieldJSON(name, "Config.Volumes")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err = unmarshalJSON([]byte(res), &result); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, ok := result["bar"]; !ok {
+		t.Fatal("Could not find volume bar set from env foo in volumes table")
+	}
+
+	_, err = buildImage(name,
+		`
+  FROM scratch
+  ENV FOO bar
+  VOLUME \${FOO}
+  `, true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err = inspectFieldJSON(name, "Config.Volumes")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err = unmarshalJSON([]byte(res), &result); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, ok := result["${FOO}"]; !ok {
+		t.Fatal("Could not find volume ${FOO} set from env foo in volumes table")
+	}
+
+	// this test in particular provides *7* backslashes and expects 6 to come back.
+	// Like above, the first escape is swallowed and the rest are treated as
+	// literals, this one is just less obvious because of all the character noise.
+
+	_, err = buildImage(name,
+		`
+  FROM scratch
+  ENV FOO bar
+  VOLUME \\\\\\\${FOO}
+  `, true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	res, err = inspectFieldJSON(name, "Config.Volumes")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if err = unmarshalJSON([]byte(res), &result); err != nil {
+		t.Fatal(err)
+	}
+
+	if _, ok := result[`\\\\\\${FOO}`]; !ok {
+		t.Fatal(`Could not find volume \\\\\\${FOO} set from env foo in volumes table`)
+	}
+
+	logDone("build - handle escapes")
+}
+
+func TestBuildOnBuildLowercase(t *testing.T) {
+	name := "testbuildonbuildlowercase"
+	name2 := "testbuildonbuildlowercase2"
+
+	defer deleteImages(name, name2)
+
+	_, err := buildImage(name,
+		`
+  FROM busybox
+  onbuild run echo quux
+  `, true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, out, err := buildImageWithOut(name2, fmt.Sprintf(`
+  FROM %s
+  `, name), true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !strings.Contains(out, "quux") {
+		t.Fatalf("Did not receive the expected echo text, got %s", out)
+	}
+
+	if strings.Contains(out, "ONBUILD ONBUILD") {
+		t.Fatalf("Got an ONBUILD ONBUILD error with no error: got %s", out)
+	}
+
+	logDone("build - handle case-insensitive onbuild statement")
+}
+
+func TestBuildEnvEscapes(t *testing.T) {
+	name := "testbuildenvescapes"
+	defer deleteAllContainers()
+	defer deleteImages(name)
+	_, err := buildImage(name,
+		`
+    FROM busybox
+    ENV TEST foo
+    CMD echo \$
+    `,
+		true)
+
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name))
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if strings.TrimSpace(out) != "$" {
+		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
+	}
+
+	logDone("build - env should handle \\$ properly")
+}
+
+func TestBuildEnvOverwrite(t *testing.T) {
+	name := "testbuildenvoverwrite"
+	defer deleteAllContainers()
+	defer deleteImages(name)
+
+	_, err := buildImage(name,
+		`
+    FROM busybox
+    ENV TEST foo
+    CMD echo ${TEST}
+    `,
+		true)
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-e", "TEST=bar", "-t", name))
+
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if strings.TrimSpace(out) != "bar" {
+		t.Fatalf("Env TEST was not overwritten with bar when foo was supplied to dockerfile: was %q", strings.TrimSpace(out))
+	}
+
+	logDone("build - env should overwrite builder ENV during run")
+}
+
 func TestBuildOnBuildForbiddenMaintainerInSourceImage(t *testing.T) {
 	name := "testbuildonbuildforbiddenmaintainerinsourceimage"
 	defer deleteImages(name)
@@ -1272,6 +1663,49 @@
 	logDone("build - expose")
 }
 
+func TestBuildEmptyEntrypointInheritance(t *testing.T) {
+	name := "testbuildentrypointinheritance"
+	name2 := "testbuildentrypointinheritance2"
+	defer deleteImages(name, name2)
+
+	_, err := buildImage(name,
+		`FROM busybox
+        ENTRYPOINT ["/bin/echo"]`,
+		true)
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err := inspectField(name, "Config.Entrypoint")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected := "[/bin/echo]"
+	if res != expected {
+		t.Fatalf("Entrypoint %s, expected %s", res, expected)
+	}
+
+	_, err = buildImage(name2,
+		fmt.Sprintf(`FROM %s
+        ENTRYPOINT []`, name),
+		true)
+	if err != nil {
+		t.Fatal(err)
+	}
+	res, err = inspectField(name2, "Config.Entrypoint")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	expected = "[]"
+
+	if res != expected {
+		t.Fatalf("Entrypoint %s, expected %s", res, expected)
+	}
+
+	logDone("build - empty entrypoint inheritance")
+}
+
 func TestBuildEmptyEntrypoint(t *testing.T) {
 	name := "testbuildentrypoint"
 	defer deleteImages(name)
@@ -2328,6 +2762,7 @@
 	name := "testbuildenvusage"
 	defer deleteImages(name)
 	dockerfile := `FROM busybox
+ENV    HOME /root
 ENV    PATH $HOME/bin:$PATH
 ENV    PATH /tmp:$PATH
 RUN    [ "$PATH" = "/tmp:$HOME/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
diff -Nru docker.io-1.3.0~dfsg1/integration-cli/docker_cli_daemon_test.go docker.io-1.3.1~dfsg1/integration-cli/docker_cli_daemon_test.go
--- docker.io-1.3.0~dfsg1/integration-cli/docker_cli_daemon_test.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/integration-cli/docker_cli_daemon_test.go	2014-10-30 13:44:46.000000000 +0000
@@ -82,3 +82,13 @@
 
 	logDone("daemon - volume refs are restored")
 }
+
+func TestDaemonStartIptablesFalse(t *testing.T) {
+	d := NewDaemon(t)
+	if err := d.Start("--iptables=false"); err != nil {
+		t.Fatalf("we should have been able to start the daemon with passing iptables=false: %v", err)
+	}
+	d.Stop()
+
+	logDone("daemon - started daemon with iptables=false")
+}
diff -Nru docker.io-1.3.0~dfsg1/integration-cli/docker_cli_run_test.go docker.io-1.3.1~dfsg1/integration-cli/docker_cli_run_test.go
--- docker.io-1.3.0~dfsg1/integration-cli/docker_cli_run_test.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/integration-cli/docker_cli_run_test.go	2014-10-30 13:44:46.000000000 +0000
@@ -2,6 +2,7 @@
 
 import (
 	"bufio"
+	"bytes"
 	"fmt"
 	"io/ioutil"
 	"net"
@@ -2374,3 +2375,68 @@
 
 	logDone("run - volumes not recreated on start")
 }
+
+func TestRunNoOutputFromPullInStdout(t *testing.T) {
+	defer deleteAllContainers()
+	// just run with unknown image
+	cmd := exec.Command(dockerBinary, "run", "asdfsg")
+	stdout := bytes.NewBuffer(nil)
+	cmd.Stdout = stdout
+	if err := cmd.Run(); err == nil {
+		t.Fatal("Run with unknown image should fail")
+	}
+	if stdout.Len() != 0 {
+		t.Fatalf("Stdout contains output from pull: %s", stdout)
+	}
+	logDone("run - no output from pull in stdout")
+}
+
+func TestRunVolumesCleanPaths(t *testing.T) {
+	defer deleteAllContainers()
+
+	if _, err := buildImage("run_volumes_clean_paths",
+		`FROM busybox
+		 VOLUME /foo/`,
+		true); err != nil {
+		t.Fatal(err)
+	}
+	defer deleteImages("run_volumes_clean_paths")
+
+	cmd := exec.Command(dockerBinary, "run", "-v", "/foo", "-v", "/bar/", "--name", "dark_helmet", "run_volumes_clean_paths")
+	if out, _, err := runCommandWithOutput(cmd); err != nil {
+		t.Fatal(err, out)
+	}
+
+	out, err := inspectFieldMap("dark_helmet", "Volumes", "/foo/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if out != "<no value>" {
+		t.Fatalf("Found unexpected volume entry for '/foo/' in volumes\n%q", out)
+	}
+
+	out, err = inspectFieldMap("dark_helmet", "Volumes", "/foo")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !strings.Contains(out, volumesStoragePath) {
+		t.Fatalf("Volume was not defined for /foo\n%q", out)
+	}
+
+	out, err = inspectFieldMap("dark_helmet", "Volumes", "/bar/")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if out != "<no value>" {
+		t.Fatalf("Found unexpected volume entry for '/bar/' in volumes\n%q", out)
+	}
+	out, err = inspectFieldMap("dark_helmet", "Volumes", "/bar")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if !strings.Contains(out, volumesStoragePath) {
+		t.Fatalf("Volume was not defined for /bar\n%q", out)
+	}
+
+	logDone("run - volume paths are cleaned")
+}
diff -Nru docker.io-1.3.0~dfsg1/integration-cli/docker_test_vars.go docker.io-1.3.1~dfsg1/integration-cli/docker_test_vars.go
--- docker.io-1.3.0~dfsg1/integration-cli/docker_test_vars.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/integration-cli/docker_test_vars.go	2014-10-30 13:44:46.000000000 +0000
@@ -16,8 +16,10 @@
 	// the private registry to use for tests
 	privateRegistryURL = "127.0.0.1:5000"
 
-	execDriverPath    = "/var/lib/docker/execdriver/native"
-	volumesConfigPath = "/var/lib/docker/volumes"
+	dockerBasePath     = "/var/lib/docker"
+	execDriverPath     = dockerBasePath + "/execdriver/native"
+	volumesConfigPath  = dockerBasePath + "/volumes"
+	volumesStoragePath = dockerBasePath + "/vfs/dir"
 
 	workingDirectory string
 )
diff -Nru docker.io-1.3.0~dfsg1/integration-cli/docker_utils.go docker.io-1.3.1~dfsg1/integration-cli/docker_utils.go
--- docker.io-1.3.0~dfsg1/integration-cli/docker_utils.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/integration-cli/docker_utils.go	2014-10-30 13:44:46.000000000 +0000
@@ -507,6 +507,16 @@
 	return strings.TrimSpace(out), nil
 }
 
+func inspectFieldMap(name, path, field string) (string, error) {
+	format := fmt.Sprintf("{{index .%s %q}}", path, field)
+	inspectCmd := exec.Command(dockerBinary, "inspect", "-f", format, name)
+	out, exitCode, err := runCommandWithOutput(inspectCmd)
+	if err != nil || exitCode != 0 {
+		return "", fmt.Errorf("failed to inspect %s: %s", name, out)
+	}
+	return strings.TrimSpace(out), nil
+}
+
 func getIDByName(name string) (string, error) {
 	return inspectField(name, "Id")
 }
diff -Nru docker.io-1.3.0~dfsg1/registry/endpoint.go docker.io-1.3.1~dfsg1/registry/endpoint.go
--- docker.io-1.3.0~dfsg1/registry/endpoint.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/registry/endpoint.go	2014-10-30 13:44:46.000000000 +0000
@@ -2,7 +2,6 @@
 
 import (
 	"encoding/json"
-	"errors"
 	"fmt"
 	"io/ioutil"
 	"net/http"
@@ -34,9 +33,9 @@
 	return hostname, DefaultAPIVersion
 }
 
-func NewEndpoint(hostname string) (*Endpoint, error) {
+func NewEndpoint(hostname string, secure bool) (*Endpoint, error) {
 	var (
-		endpoint        Endpoint
+		endpoint        = Endpoint{secure: secure}
 		trimmedHostname string
 		err             error
 	)
@@ -49,14 +48,27 @@
 		return nil, err
 	}
 
+	// Try HTTPS ping to registry
 	endpoint.URL.Scheme = "https"
 	if _, err := endpoint.Ping(); err != nil {
-		log.Debugf("Registry %s does not work (%s), falling back to http", endpoint, err)
-		// TODO: Check if http fallback is enabled
+
+		//TODO: triggering highland build can be done there without "failing"
+
+		if secure {
+			// If registry is secure and HTTPS failed, show user the error and tell them about `--insecure-registry`
+			// in case that's what they need. DO NOT accept unknown CA certificates, and DO NOT fallback to HTTP.
+			return nil, fmt.Errorf("Invalid registry endpoint %s: %v. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry %s` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/%s/ca.crt", endpoint, err, endpoint.URL.Host, endpoint.URL.Host)
+		}
+
+		// If registry is insecure and HTTPS failed, fallback to HTTP.
+		log.Debugf("Error from registry %q marked as insecure: %v. Insecurely falling back to HTTP", endpoint, err)
 		endpoint.URL.Scheme = "http"
-		if _, err = endpoint.Ping(); err != nil {
-			return nil, errors.New("Invalid Registry endpoint: " + err.Error())
+		_, err2 := endpoint.Ping()
+		if err2 == nil {
+			return &endpoint, nil
 		}
+
+		return nil, fmt.Errorf("Invalid registry endpoint %q. HTTPS attempt: %v. HTTP attempt: %v", endpoint, err, err2)
 	}
 
 	return &endpoint, nil
@@ -65,6 +77,7 @@
 type Endpoint struct {
 	URL     *url.URL
 	Version APIVersion
+	secure  bool
 }
 
 // Get the formated URL for the root of this registry Endpoint
@@ -88,7 +101,7 @@
 		return RegistryInfo{Standalone: false}, err
 	}
 
-	resp, _, err := doRequest(req, nil, ConnectTimeout)
+	resp, _, err := doRequest(req, nil, ConnectTimeout, e.secure)
 	if err != nil {
 		return RegistryInfo{Standalone: false}, err
 	}
@@ -127,3 +140,19 @@
 	log.Debugf("RegistryInfo.Standalone: %t", info.Standalone)
 	return info, nil
 }
+
+// IsSecure returns false if the provided hostname is part of the list of insecure registries.
+// Insecure registries accept HTTP and/or accept HTTPS with certificates from unknown CAs.
+func IsSecure(hostname string, insecureRegistries []string) bool {
+	if hostname == IndexServerAddress() {
+		return true
+	}
+
+	for _, h := range insecureRegistries {
+		if hostname == h {
+			return false
+		}
+	}
+
+	return true
+}
diff -Nru docker.io-1.3.0~dfsg1/registry/registry.go docker.io-1.3.1~dfsg1/registry/registry.go
--- docker.io-1.3.0~dfsg1/registry/registry.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/registry/registry.go	2014-10-30 13:44:46.000000000 +0000
@@ -14,6 +14,7 @@
 	"strings"
 	"time"
 
+	"github.com/docker/docker/pkg/log"
 	"github.com/docker/docker/utils"
 )
 
@@ -35,13 +36,21 @@
 	ConnectTimeout
 )
 
-func newClient(jar http.CookieJar, roots *x509.CertPool, cert *tls.Certificate, timeout TimeoutType) *http.Client {
-	tlsConfig := tls.Config{RootCAs: roots}
+func newClient(jar http.CookieJar, roots *x509.CertPool, cert *tls.Certificate, timeout TimeoutType, secure bool) *http.Client {
+	tlsConfig := tls.Config{
+		RootCAs: roots,
+		// Avoid fallback to SSL protocols < TLS1.0
+		MinVersion: tls.VersionTLS10,
+	}
 
 	if cert != nil {
 		tlsConfig.Certificates = append(tlsConfig.Certificates, *cert)
 	}
 
+	if !secure {
+		tlsConfig.InsecureSkipVerify = true
+	}
+
 	httpTransport := &http.Transport{
 		DisableKeepAlives: true,
 		Proxy:             http.ProxyFromEnvironment,
@@ -78,69 +87,76 @@
 	}
 }
 
-func doRequest(req *http.Request, jar http.CookieJar, timeout TimeoutType) (*http.Response, *http.Client, error) {
-	hasFile := func(files []os.FileInfo, name string) bool {
-		for _, f := range files {
-			if f.Name() == name {
-				return true
-			}
-		}
-		return false
-	}
-
-	hostDir := path.Join("/etc/docker/certs.d", req.URL.Host)
-	fs, err := ioutil.ReadDir(hostDir)
-	if err != nil && !os.IsNotExist(err) {
-		return nil, nil, err
-	}
-
+func doRequest(req *http.Request, jar http.CookieJar, timeout TimeoutType, secure bool) (*http.Response, *http.Client, error) {
 	var (
 		pool  *x509.CertPool
 		certs []*tls.Certificate
 	)
 
-	for _, f := range fs {
-		if strings.HasSuffix(f.Name(), ".crt") {
-			if pool == nil {
-				pool = x509.NewCertPool()
-			}
-			data, err := ioutil.ReadFile(path.Join(hostDir, f.Name()))
-			if err != nil {
-				return nil, nil, err
-			}
-			pool.AppendCertsFromPEM(data)
+	if secure && req.URL.Scheme == "https" {
+		hasFile := func(files []os.FileInfo, name string) bool {
+			for _, f := range files {
+				if f.Name() == name {
+					return true
+				}
+			}
+			return false
 		}
-		if strings.HasSuffix(f.Name(), ".cert") {
-			certName := f.Name()
-			keyName := certName[:len(certName)-5] + ".key"
-			if !hasFile(fs, keyName) {
-				return nil, nil, fmt.Errorf("Missing key %s for certificate %s", keyName, certName)
-			}
-			cert, err := tls.LoadX509KeyPair(path.Join(hostDir, certName), path.Join(hostDir, keyName))
-			if err != nil {
-				return nil, nil, err
-			}
-			certs = append(certs, &cert)
+
+		hostDir := path.Join("/etc/docker/certs.d", req.URL.Host)
+		log.Debugf("hostDir: %s", hostDir)
+		fs, err := ioutil.ReadDir(hostDir)
+		if err != nil && !os.IsNotExist(err) {
+			return nil, nil, err
 		}
-		if strings.HasSuffix(f.Name(), ".key") {
-			keyName := f.Name()
-			certName := keyName[:len(keyName)-4] + ".cert"
-			if !hasFile(fs, certName) {
-				return nil, nil, fmt.Errorf("Missing certificate %s for key %s", certName, keyName)
+
+		for _, f := range fs {
+			if strings.HasSuffix(f.Name(), ".crt") {
+				if pool == nil {
+					pool = x509.NewCertPool()
+				}
+				log.Debugf("crt: %s", hostDir+"/"+f.Name())
+				data, err := ioutil.ReadFile(path.Join(hostDir, f.Name()))
+				if err != nil {
+					return nil, nil, err
+				}
+				pool.AppendCertsFromPEM(data)
+			}
+			if strings.HasSuffix(f.Name(), ".cert") {
+				certName := f.Name()
+				keyName := certName[:len(certName)-5] + ".key"
+				log.Debugf("cert: %s", hostDir+"/"+f.Name())
+				if !hasFile(fs, keyName) {
+					return nil, nil, fmt.Errorf("Missing key %s for certificate %s", keyName, certName)
+				}
+				cert, err := tls.LoadX509KeyPair(path.Join(hostDir, certName), path.Join(hostDir, keyName))
+				if err != nil {
+					return nil, nil, err
+				}
+				certs = append(certs, &cert)
+			}
+			if strings.HasSuffix(f.Name(), ".key") {
+				keyName := f.Name()
+				certName := keyName[:len(keyName)-4] + ".cert"
+				log.Debugf("key: %s", hostDir+"/"+f.Name())
+				if !hasFile(fs, certName) {
+					return nil, nil, fmt.Errorf("Missing certificate %s for key %s", certName, keyName)
+				}
 			}
 		}
 	}
 
 	if len(certs) == 0 {
-		client := newClient(jar, pool, nil, timeout)
+		client := newClient(jar, pool, nil, timeout, secure)
 		res, err := client.Do(req)
 		if err != nil {
 			return nil, nil, err
 		}
 		return res, client, nil
 	}
+
 	for i, cert := range certs {
-		client := newClient(jar, pool, cert, timeout)
+		client := newClient(jar, pool, cert, timeout, secure)
 		res, err := client.Do(req)
 		// If this is the last cert, otherwise, continue to next cert if 403 or 5xx
 		if i == len(certs)-1 || err == nil && res.StatusCode != 403 && res.StatusCode < 500 {
diff -Nru docker.io-1.3.0~dfsg1/registry/registry_test.go docker.io-1.3.1~dfsg1/registry/registry_test.go
--- docker.io-1.3.0~dfsg1/registry/registry_test.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/registry/registry_test.go	2014-10-30 13:44:46.000000000 +0000
@@ -18,7 +18,7 @@
 
 func spawnTestRegistrySession(t *testing.T) *Session {
 	authConfig := &AuthConfig{}
-	endpoint, err := NewEndpoint(makeURL("/v1/"))
+	endpoint, err := NewEndpoint(makeURL("/v1/"), false)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -30,7 +30,7 @@
 }
 
 func TestPingRegistryEndpoint(t *testing.T) {
-	ep, err := NewEndpoint(makeURL("/v1/"))
+	ep, err := NewEndpoint(makeURL("/v1/"), false)
 	if err != nil {
 		t.Fatal(err)
 	}
diff -Nru docker.io-1.3.0~dfsg1/registry/service.go docker.io-1.3.1~dfsg1/registry/service.go
--- docker.io-1.3.0~dfsg1/registry/service.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/registry/service.go	2014-10-30 13:44:46.000000000 +0000
@@ -13,12 +13,15 @@
 //  'pull': Download images from any registry (TODO)
 //  'push': Upload images to any registry (TODO)
 type Service struct {
+	insecureRegistries []string
 }
 
 // NewService returns a new instance of Service ready to be
 // installed no an engine.
-func NewService() *Service {
-	return &Service{}
+func NewService(insecureRegistries []string) *Service {
+	return &Service{
+		insecureRegistries: insecureRegistries,
+	}
 }
 
 // Install installs registry capabilities to eng.
@@ -32,15 +35,12 @@
 // and returns OK if authentication was sucessful.
 // It can be used to verify the validity of a client's credentials.
 func (s *Service) Auth(job *engine.Job) engine.Status {
-	var (
-		err        error
-		authConfig = &AuthConfig{}
-	)
+	var authConfig = new(AuthConfig)
 
 	job.GetenvJson("authConfig", authConfig)
-	// TODO: this is only done here because auth and registry need to be merged into one pkg
+
 	if addr := authConfig.ServerAddress; addr != "" && addr != IndexServerAddress() {
-		endpoint, err := NewEndpoint(addr)
+		endpoint, err := NewEndpoint(addr, IsSecure(addr, s.insecureRegistries))
 		if err != nil {
 			return job.Error(err)
 		}
@@ -49,11 +49,13 @@
 		}
 		authConfig.ServerAddress = endpoint.String()
 	}
+
 	status, err := Login(authConfig, HTTPRequestFactory(nil))
 	if err != nil {
 		return job.Error(err)
 	}
 	job.Printf("%s\n", status)
+
 	return engine.StatusOK
 }
 
@@ -89,7 +91,10 @@
 	if err != nil {
 		return job.Error(err)
 	}
-	endpoint, err := NewEndpoint(hostname)
+
+	secure := IsSecure(hostname, s.insecureRegistries)
+
+	endpoint, err := NewEndpoint(hostname, secure)
 	if err != nil {
 		return job.Error(err)
 	}
diff -Nru docker.io-1.3.0~dfsg1/registry/session.go docker.io-1.3.1~dfsg1/registry/session.go
--- docker.io-1.3.0~dfsg1/registry/session.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/registry/session.go	2014-10-30 13:44:46.000000000 +0000
@@ -64,7 +64,7 @@
 }
 
 func (r *Session) doRequest(req *http.Request) (*http.Response, *http.Client, error) {
-	return doRequest(req, r.jar, r.timeout)
+	return doRequest(req, r.jar, r.timeout, r.indexEndpoint.secure)
 }
 
 // Retrieve the history of a given image from the Registry.
diff -Nru docker.io-1.3.0~dfsg1/runconfig/merge.go docker.io-1.3.1~dfsg1/runconfig/merge.go
--- docker.io-1.3.0~dfsg1/runconfig/merge.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/runconfig/merge.go	2014-10-30 13:44:46.000000000 +0000
@@ -88,7 +88,10 @@
 		if len(userConf.Cmd) == 0 {
 			userConf.Cmd = imageConf.Cmd
 		}
-		userConf.Entrypoint = imageConf.Entrypoint
+
+		if userConf.Entrypoint == nil {
+			userConf.Entrypoint = imageConf.Entrypoint
+		}
 	}
 	if userConf.WorkingDir == "" {
 		userConf.WorkingDir = imageConf.WorkingDir
diff -Nru docker.io-1.3.0~dfsg1/volumes/repository.go docker.io-1.3.1~dfsg1/volumes/repository.go
--- docker.io-1.3.0~dfsg1/volumes/repository.go	2014-10-15 19:15:24.000000000 +0000
+++ docker.io-1.3.1~dfsg1/volumes/repository.go	2014-10-30 13:44:46.000000000 +0000
@@ -55,6 +55,7 @@
 			return nil, err
 		}
 	}
+	path = filepath.Clean(path)
 
 	path, err = filepath.EvalSymlinks(path)
 	if err != nil {
@@ -126,7 +127,7 @@
 	if err != nil {
 		return nil
 	}
-	return r.volumes[path]
+	return r.volumes[filepath.Clean(path)]
 }
 
 func (r *Repository) Add(volume *Volume) error {
@@ -160,7 +161,7 @@
 	if err != nil {
 		return err
 	}
-	volume := r.get(path)
+	volume := r.get(filepath.Clean(path))
 	if volume == nil {
 		return fmt.Errorf("Volume %s does not exist", path)
 	}

Reply to: