mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-06-06 05:30:57 +00:00
Re-work the way checksum matching works against Release file
Break up URL into base part and relative path. Match checksum against relative path and never against full URL. This might be fixing security issue if aptly was incorrectly matching against wrong part of Release file.
This commit is contained in:
+9
-6
@@ -5,6 +5,7 @@ import (
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -38,19 +39,19 @@ var compressionMethods = []struct {
|
||||
|
||||
// DownloadTryCompression tries to download from URL .bz2, .gz and raw extension until
|
||||
// it finds existing file.
|
||||
func DownloadTryCompression(downloader aptly.Downloader, url string, expectedChecksums map[string]utils.ChecksumInfo, ignoreMismatch bool, maxTries int) (io.Reader, *os.File, error) {
|
||||
func DownloadTryCompression(downloader aptly.Downloader, baseURL *url.URL, path string, expectedChecksums map[string]utils.ChecksumInfo, ignoreMismatch bool, maxTries int) (io.Reader, *os.File, error) {
|
||||
var err error
|
||||
|
||||
for _, method := range compressionMethods {
|
||||
var file *os.File
|
||||
|
||||
tryURL := url + method.extenstion
|
||||
tryPath := path + method.extenstion
|
||||
foundChecksum := false
|
||||
|
||||
bestSuffix := ""
|
||||
|
||||
for suffix := range expectedChecksums {
|
||||
if strings.HasSuffix(tryURL, suffix) {
|
||||
if strings.HasSuffix(tryPath, suffix) {
|
||||
foundChecksum = true
|
||||
if len(suffix) > len(bestSuffix) {
|
||||
bestSuffix = suffix
|
||||
@@ -58,15 +59,17 @@ func DownloadTryCompression(downloader aptly.Downloader, url string, expectedChe
|
||||
}
|
||||
}
|
||||
|
||||
tryURL := baseURL.ResolveReference(&url.URL{Path: tryPath})
|
||||
|
||||
if foundChecksum {
|
||||
expected := expectedChecksums[bestSuffix]
|
||||
file, err = DownloadTempWithChecksum(downloader, tryURL, &expected, ignoreMismatch, maxTries)
|
||||
file, err = DownloadTempWithChecksum(downloader, tryURL.String(), &expected, ignoreMismatch, maxTries)
|
||||
} else {
|
||||
if !ignoreMismatch {
|
||||
continue
|
||||
}
|
||||
|
||||
file, err = DownloadTemp(downloader, tryURL)
|
||||
file, err = DownloadTemp(downloader, tryURL.String())
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@@ -86,7 +89,7 @@ func DownloadTryCompression(downloader aptly.Downloader, url string, expectedChe
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = fmt.Errorf("no candidates for %s found", url)
|
||||
err = fmt.Errorf("no candidates for %s found", baseURL.ResolveReference(&url.URL{Path: path}))
|
||||
}
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
+17
-10
@@ -3,13 +3,16 @@ package http
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"net/url"
|
||||
|
||||
"github.com/smira/aptly/utils"
|
||||
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
type CompressionSuite struct{}
|
||||
type CompressionSuite struct {
|
||||
baseURL *url.URL
|
||||
}
|
||||
|
||||
var _ = Suite(&CompressionSuite{})
|
||||
|
||||
@@ -20,6 +23,10 @@ const (
|
||||
rawData = "test"
|
||||
)
|
||||
|
||||
func (s *CompressionSuite) SetUpTest(c *C) {
|
||||
s.baseURL, _ = url.Parse("http://example.com/")
|
||||
}
|
||||
|
||||
func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
||||
var buf []byte
|
||||
|
||||
@@ -34,7 +41,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
||||
buf = make([]byte, 4)
|
||||
d := NewFakeDownloader()
|
||||
d.ExpectResponse("http://example.com/file.bz2", bzipData)
|
||||
r, file, err := DownloadTryCompression(d, "http://example.com/file", expectedChecksums, false, 1)
|
||||
r, file, err := DownloadTryCompression(d, s.baseURL, "file", expectedChecksums, false, 1)
|
||||
c.Assert(err, IsNil)
|
||||
defer file.Close()
|
||||
io.ReadFull(r, buf)
|
||||
@@ -46,7 +53,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
||||
d = NewFakeDownloader()
|
||||
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
||||
d.ExpectResponse("http://example.com/file.gz", gzipData)
|
||||
r, file, err = DownloadTryCompression(d, "http://example.com/file", expectedChecksums, false, 1)
|
||||
r, file, err = DownloadTryCompression(d, s.baseURL, "file", expectedChecksums, false, 1)
|
||||
c.Assert(err, IsNil)
|
||||
defer file.Close()
|
||||
io.ReadFull(r, buf)
|
||||
@@ -59,7 +66,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
||||
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
||||
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
||||
d.ExpectResponse("http://example.com/file.xz", xzData)
|
||||
r, file, err = DownloadTryCompression(d, "http://example.com/file", expectedChecksums, false, 1)
|
||||
r, file, err = DownloadTryCompression(d, s.baseURL, "file", expectedChecksums, false, 1)
|
||||
c.Assert(err, IsNil)
|
||||
defer file.Close()
|
||||
io.ReadFull(r, buf)
|
||||
@@ -73,7 +80,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
||||
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
||||
d.ExpectError("http://example.com/file.xz", &Error{Code: 404})
|
||||
d.ExpectResponse("http://example.com/file", rawData)
|
||||
r, file, err = DownloadTryCompression(d, "http://example.com/file", expectedChecksums, false, 1)
|
||||
r, file, err = DownloadTryCompression(d, s.baseURL, "file", expectedChecksums, false, 1)
|
||||
c.Assert(err, IsNil)
|
||||
defer file.Close()
|
||||
io.ReadFull(r, buf)
|
||||
@@ -84,7 +91,7 @@ func (s *CompressionSuite) TestDownloadTryCompression(c *C) {
|
||||
d = NewFakeDownloader()
|
||||
d.ExpectError("http://example.com/file.bz2", &Error{Code: 404})
|
||||
d.ExpectResponse("http://example.com/file.gz", "x")
|
||||
_, _, err = DownloadTryCompression(d, "http://example.com/file", nil, true, 1)
|
||||
_, _, err = DownloadTryCompression(d, s.baseURL, "file", nil, true, 1)
|
||||
c.Assert(err, ErrorMatches, "unexpected EOF")
|
||||
c.Assert(d.Empty(), Equals, true)
|
||||
}
|
||||
@@ -102,7 +109,7 @@ func (s *CompressionSuite) TestDownloadTryCompressionLongestSuffix(c *C) {
|
||||
buf = make([]byte, 4)
|
||||
d := NewFakeDownloader()
|
||||
d.ExpectResponse("http://example.com/subdir/file.bz2", bzipData)
|
||||
r, file, err := DownloadTryCompression(d, "http://example.com/subdir/file", expectedChecksums, false, 1)
|
||||
r, file, err := DownloadTryCompression(d, s.baseURL, "subdir/file", expectedChecksums, false, 1)
|
||||
c.Assert(err, IsNil)
|
||||
defer file.Close()
|
||||
io.ReadFull(r, buf)
|
||||
@@ -112,7 +119,7 @@ func (s *CompressionSuite) TestDownloadTryCompressionLongestSuffix(c *C) {
|
||||
|
||||
func (s *CompressionSuite) TestDownloadTryCompressionErrors(c *C) {
|
||||
d := NewFakeDownloader()
|
||||
_, _, err := DownloadTryCompression(d, "http://example.com/file", nil, true, 1)
|
||||
_, _, err := DownloadTryCompression(d, s.baseURL, "file", nil, true, 1)
|
||||
c.Assert(err, ErrorMatches, "unexpected request.*")
|
||||
|
||||
d = NewFakeDownloader()
|
||||
@@ -120,7 +127,7 @@ func (s *CompressionSuite) TestDownloadTryCompressionErrors(c *C) {
|
||||
d.ExpectError("http://example.com/file.gz", &Error{Code: 404})
|
||||
d.ExpectError("http://example.com/file.xz", &Error{Code: 404})
|
||||
d.ExpectError("http://example.com/file", errors.New("403"))
|
||||
_, _, err = DownloadTryCompression(d, "http://example.com/file", nil, true, 1)
|
||||
_, _, err = DownloadTryCompression(d, s.baseURL, "file", nil, true, 1)
|
||||
c.Assert(err, ErrorMatches, "403")
|
||||
|
||||
d = NewFakeDownloader()
|
||||
@@ -134,6 +141,6 @@ func (s *CompressionSuite) TestDownloadTryCompressionErrors(c *C) {
|
||||
"file.xz": {Size: 7},
|
||||
"file": {Size: 7},
|
||||
}
|
||||
_, _, err = DownloadTryCompression(d, "http://example.com/file", expectedChecksums, false, 1)
|
||||
_, _, err = DownloadTryCompression(d, s.baseURL, "file", expectedChecksums, false, 1)
|
||||
c.Assert(err, ErrorMatches, "checksums don't match.*")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user