Merge lp:~dpb/landscape-charm/strip-url-newline-1411353 into lp:~landscape/landscape-charm/trunk

Proposed by David Britton
Status: Merged
Approved by: David Britton
Approved revision: 218
Merged at revision: 217
Proposed branch: lp:~dpb/landscape-charm/strip-url-newline-1411353
Merge into: lp:~landscape/landscape-charm/trunk
Diff against target: 82 lines (+34/-5)
2 files modified
hooks/hooks.py (+4/-2)
hooks/test_hooks.py (+30/-3)
To merge this branch: bzr merge lp:~dpb/landscape-charm/strip-url-newline-1411353
Reviewer Review Type Date Requested Status
Andreas Hasenack Approve
Adam Collard (community) Approve
Review via email: mp+246628@code.launchpad.net

Commit message

Strip newlines from url before passing to cURL.

Description of the change

Strip newlines from url before passing to cURL.

To post a comment you must log in.
Revision history for this message
Adam Collard (adam-collard) wrote :

Change is good, I think the tests need to be modified as suggested below, to make them easier to grok

review: Approve
Revision history for this message
Andreas Hasenack (ahasenack) wrote :

+1, just a minor comment about the test.

review: Approve
218. By David Britton

sparkiegeek[diff]: check url explicitly
andreas[diff]: catch \r as well

Revision history for this message
David Britton (dpb) wrote :
Download full text (3.5 KiB)

Thanks, I've addressed all feedback.

On Thu, Jan 15, 2015 at 1:12 PM, Andreas Hasenack <email address hidden>
wrote:

> Review: Approve
>
> +1, just a minor comment about the test.
>
>
> Diff comments:
>
> > === modified file 'hooks/hooks.py'
> > --- hooks/hooks.py 2015-01-12 10:40:19 +0000
> > +++ hooks/hooks.py 2015-01-15 19:11:45 +0000
> > @@ -501,11 +501,13 @@
> > notify_website_relation()
> >
> >
> > -def _download_file(url):
> > +def _download_file(url, Curl=pycurl.Curl):
> > """ Download from a url and save to the filename given """
> > + # Fix for CVE-2014-8150, urls cannot end with newline
> > + url = url.rstrip()
> > buf = cStringIO.StringIO()
> > juju.juju_log("Fetching License: %s" % url)
> > - curl = pycurl.Curl()
> > + curl = Curl()
> > curl.setopt(pycurl.URL, str(url))
> > curl.setopt(pycurl.WRITEFUNCTION, buf.write)
> > curl.perform()
> >
> > === modified file 'hooks/test_hooks.py'
> > --- hooks/test_hooks.py 2014-12-10 22:08:57 +0000
> > +++ hooks/test_hooks.py 2015-01-15 19:11:45 +0000
> > @@ -12,6 +12,23 @@
> > import yaml
> >
> >
> > +class CurlStub(object):
> > +
> > + def __init__(self, result=None, infos=None, error=None):
> > + pass
> > +
> > + def setopt(self, option, value):
> > + if option == pycurl.URL:
> > + if "\n" in value:
>
> The curl patch (http://curl.haxx.se/CVE-2014-8150.patch) blocks both \n
> and \r, can we do the same in the test just to be consistent?
>
> > + raise AssertionError("URL cannot contain newline")
> > +
> > + def perform(self):
> > + pass
> > +
> > + def close(self):
> > + pass
> > +
> > +
> > class TestJuju(object):
> > """
> > Testing object to intercept juju calls and inject data, or make sure
> > @@ -908,13 +925,19 @@
> > filename = self.makeFile()
> > with open(filename, "w") as fp:
> > fp.write("foobar")
> > - output = hooks._download_file("file://%s" % filename)
> > + output = hooks._download_file("file:///%s" % filename)
> > self.assertIn("foobar", output)
> >
> > + def test__download_file_success_trailing_newline(self):
> > + """Test that newlines are stripped before passing to curl.
> CVE-2014-8150."""
> > + # put two newlines, since that could be a common pattern in a
> text
> > + # file when using an editor
> > + hooks._download_file("http://example.com/\n\n", Curl=CurlStub)
> > +
> > def test__download_file_failure(self):
> > """The fail path of download file raises an exception."""
> > self.assertRaises(
> > - pycurl.error, hooks._download_file, "file://FOO/NO/EXIST")
> > + pycurl.error, hooks._download_file, "file:///FOO/NO/EXIST")
> >
> > def test__replace_in_file(self):
> > """
> > @@ -962,7 +985,7 @@
> > source = self.makeFile()
> > with open(source, "w") as fp:
> > fp.write("LICENSE_FILE_TEXT from curl")
> > - hooks.juju.config["license-file"] = "file://%s" % source
> > + hooks.juju.config["license-file"] = "file:///%s" % source
> > ho...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hooks/hooks.py'
2--- hooks/hooks.py 2015-01-12 10:40:19 +0000
3+++ hooks/hooks.py 2015-01-15 20:51:34 +0000
4@@ -501,11 +501,13 @@
5 notify_website_relation()
6
7
8-def _download_file(url):
9+def _download_file(url, Curl=pycurl.Curl):
10 """ Download from a url and save to the filename given """
11+ # Fix for CVE-2014-8150, urls cannot end with newline
12+ url = url.rstrip()
13 buf = cStringIO.StringIO()
14 juju.juju_log("Fetching License: %s" % url)
15- curl = pycurl.Curl()
16+ curl = Curl()
17 curl.setopt(pycurl.URL, str(url))
18 curl.setopt(pycurl.WRITEFUNCTION, buf.write)
19 curl.perform()
20
21=== modified file 'hooks/test_hooks.py'
22--- hooks/test_hooks.py 2014-12-10 22:08:57 +0000
23+++ hooks/test_hooks.py 2015-01-15 20:51:34 +0000
24@@ -12,6 +12,26 @@
25 import yaml
26
27
28+class CurlStub(object):
29+
30+ urls = []
31+
32+ def __init__(self, result=None, infos=None, error=None):
33+ pass
34+
35+ def setopt(self, option, value):
36+ if option == pycurl.URL:
37+ if "\n" in value or "\r" in value:
38+ raise AssertionError("URL cannot contain linefeed or newline")
39+ self.urls.append(value)
40+
41+ def perform(self):
42+ pass
43+
44+ def close(self):
45+ pass
46+
47+
48 class TestJuju(object):
49 """
50 Testing object to intercept juju calls and inject data, or make sure
51@@ -908,13 +928,20 @@
52 filename = self.makeFile()
53 with open(filename, "w") as fp:
54 fp.write("foobar")
55- output = hooks._download_file("file://%s" % filename)
56+ output = hooks._download_file("file:///%s" % filename)
57 self.assertIn("foobar", output)
58
59+ def test__download_file_success_trailing_newline(self):
60+ """Test that newlines are stripped before passing to curl. CVE-2014-8150."""
61+ # put two newlines, since that could be a common pattern in a text
62+ # file when using an editor
63+ hooks._download_file("http://example.com/\n\n", Curl=CurlStub)
64+ self.assertEqual(["http://example.com/"], CurlStub.urls)
65+
66 def test__download_file_failure(self):
67 """The fail path of download file raises an exception."""
68 self.assertRaises(
69- pycurl.error, hooks._download_file, "file://FOO/NO/EXIST")
70+ pycurl.error, hooks._download_file, "file:///FOO/NO/EXIST")
71
72 def test__replace_in_file(self):
73 """
74@@ -962,7 +989,7 @@
75 source = self.makeFile()
76 with open(source, "w") as fp:
77 fp.write("LICENSE_FILE_TEXT from curl")
78- hooks.juju.config["license-file"] = "file://%s" % source
79+ hooks.juju.config["license-file"] = "file:///%s" % source
80 hooks._install_license()
81 self.assertFileContains(
82 hooks.LANDSCAPE_LICENSE_DEST, "LICENSE_FILE_TEXT from curl")

Subscribers

People subscribed via source and target branches