Hello community, here is the log from the commit of package python for openSUSE:11.2 checked in at Fri May 6 15:19:56 CEST 2011.
md5sum: PATCHINFO/SWAMP-PROOFREAD-DONE/cronie.patch.box.40662: No such file or directory readline() on closed filehandle PATCHINFO at /work/cd/lib/putonftp/Patchinfo.pm line 41. Patchinfo file has no description -------- --- old-versions/11.2/UPDATES/all/python/python-base.changes 2010-10-27 20:04:05.000000000 +0200 +++ 11.2/python/python-base.changes 2011-05-02 18:29:10.000000000 +0200 @@ -1,0 +2,15 @@ +Mon May 2 16:04:49 UTC 2011 - jmate...@novell.com + +- fixed a security flaw where malicious sites could redirect + Python application from http to a local file + (CVE-2011-1521, bnc#682554) + +------------------------------------------------------------------- +Thu Mar 17 18:48:57 UTC 2011 - jmate...@novell.com + +- fixed information disclosure in CGIHTTPServer (CVE-2011-1015, + bnc#674646) +- fixed race condition in Makefile which randomly failed + parallel builds ( http://bugs.python.org/issue10013 ) + +------------------------------------------------------------------- python.changes: same change calling whatdependson for 11.2-i586 New: ---- python-2.6-CVE-2011-1015-CGIHTTPServer.patch python-2.7-CVE-2011-1521-fileurl.patch python-2.7-fix-parallel-make.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-base.spec ++++++ --- /var/tmp/diff_new_pack.qzi2g9/_old 2011-05-06 15:11:54.000000000 +0200 +++ /var/tmp/diff_new_pack.qzi2g9/_new 2011-05-06 15:11:54.000000000 +0200 @@ -1,7 +1,7 @@ # -# spec file for package python-base (Version 2.6.2) +# spec file for package python-base # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -33,7 +33,7 @@ # Summary: Python Interpreter base package Version: 2.6.2 -Release: 6.<RELEASE6> +Release: 6.<RELEASE9> %define tarname Python-%{version} Source0: %{tarname}.tar.bz2 Source1: macros.python @@ -53,6 +53,9 @@ Patch41: python-2.6-audioop-1.patch Patch42: python-2.6-audioop-2.patch Patch43: smtpd-dos.patch +Patch44: python-2.6-CVE-2011-1015-CGIHTTPServer.patch +Patch45: python-2.7-fix-parallel-make.patch +Patch46: python-2.7-CVE-2011-1521-fileurl.patch # expat patches Patch70: expat-CVE-2009-3560.patch Patch71: expat-CVE-2009-3720.patch @@ -147,6 +150,9 @@ %patch41 %patch42 %patch43 +%patch44 -p1 +%patch45 -p1 +%patch46 -p1 # expat: pushd Modules/expat %patch70 -p1 ++++++ python-doc.spec ++++++ --- /var/tmp/diff_new_pack.qzi2g9/_old 2011-05-06 15:11:54.000000000 +0200 +++ /var/tmp/diff_new_pack.qzi2g9/_new 2011-05-06 15:11:54.000000000 +0200 @@ -1,7 +1,7 @@ # -# spec file for package python-doc (Version 2.6) +# spec file for package python-doc # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -24,7 +24,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-build Summary: Additional Package Documentation for Python. Version: 2.6 -Release: 6.<RELEASE4> +Release: 6.<RELEASE6> %define pyver 2.6.2 BuildArch: noarch %define tarname Python-%{pyver} ++++++ python.spec ++++++ --- /var/tmp/diff_new_pack.qzi2g9/_old 2011-05-06 15:11:54.000000000 +0200 +++ /var/tmp/diff_new_pack.qzi2g9/_new 2011-05-06 15:11:54.000000000 +0200 @@ -1,7 +1,7 @@ # -# spec file for package python (Version 2.6.2) +# spec file for package python # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -35,7 +35,7 @@ Obsoletes: python-nothreads python21 python-elementtree python-sqlite Summary: Python Interpreter Version: 2.6.2 -Release: 6.<RELEASE6> +Release: 6.<RELEASE9> Requires: python-base = %{version} %define tarname Python-%{version} Source0: %{tarname}.tar.bz2 ++++++ python-2.6-CVE-2011-1015-CGIHTTPServer.patch ++++++ # HG changeset patch # User Gregory P. Smith <g...@mad-scientist.com> # Date 1238999606 0 # Node ID c6c4398293bd682b355f1050bb16bb3e18c8b40f # Parent e363958fcd70a43ad07b39df999552d0fa1cefc1 - Issue #2254: Fix CGIHTTPServer information disclosure. Relative paths are now collapsed within the url properly before looking in cgi_directories. Index: Python-2.6.2/Lib/CGIHTTPServer.py =================================================================== --- Python-2.6.2.orig/Lib/CGIHTTPServer.py +++ Python-2.6.2/Lib/CGIHTTPServer.py @@ -70,27 +70,20 @@ class CGIHTTPRequestHandler(SimpleHTTPSe return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self) def is_cgi(self): - """Test whether self.path corresponds to a CGI script, - and return a boolean. + """Test whether self.path corresponds to a CGI script. - This function sets self.cgi_info to a tuple (dir, rest) - when it returns True, where dir is the directory part before - the CGI script name. Note that rest begins with a - slash if it is not empty. - - The default implementation tests whether the path - begins with one of the strings in the list - self.cgi_directories (and the next character is a '/' - or the end of the string). + Returns True and updates the cgi_info attribute to the tuple + (dir, rest) if self.path requires running a CGI script. + Returns False otherwise. + + The default implementation tests whether the normalized url + path begins with one of the strings in self.cgi_directories + (and the next character is a '/' or the end of the string). """ - - path = self.path - - for x in self.cgi_directories: - i = len(x) - if path[:i] == x and (not path[i:] or path[i] == '/'): - self.cgi_info = path[:i], path[i+1:] - return True + splitpath = _url_collapse_path_split(self.path) + if splitpath[0] in self.cgi_directories: + self.cgi_info = splitpath + return True return False cgi_directories = ['/cgi-bin', '/htbin'] @@ -330,6 +323,46 @@ class CGIHTTPRequestHandler(SimpleHTTPSe self.log_message("CGI script exited OK") +# TODO(gregory.p.smith): Move this into an appropriate library. +def _url_collapse_path_split(path): + """ + Given a URL path, remove extra '/'s and '.' path elements and collapse + any '..' references. + + Implements something akin to RFC-2396 5.2 step 6 to parse relative paths. + + Returns: A tuple of (head, tail) where tail is everything after the final / + and head is everything before it. Head will always start with a '/' and, + if it contains anything else, never have a trailing '/'. + + Raises: IndexError if too many '..' occur within the path. + """ + # Similar to os.path.split(os.path.normpath(path)) but specific to URL + # path semantics rather than local operating system semantics. + path_parts = [] + for part in path.split('/'): + if part == '.': + path_parts.append('') + else: + path_parts.append(part) + # Filter out blank non trailing parts before consuming the '..'. + path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:] + if path_parts: + tail_part = path_parts.pop() + else: + tail_part = '' + head_parts = [] + for part in path_parts: + if part == '..': + head_parts.pop() + else: + head_parts.append(part) + if tail_part and tail_part == '..': + head_parts.pop() + tail_part = '' + return ('/' + '/'.join(head_parts), tail_part) + + nobody = None def nobody_uid(): Index: Python-2.6.2/Lib/test/test_httpservers.py =================================================================== --- Python-2.6.2.orig/Lib/test/test_httpservers.py +++ Python-2.6.2/Lib/test/test_httpservers.py @@ -7,6 +7,7 @@ Josip Dzolonga, and Michael Otteneder fo from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler from CGIHTTPServer import CGIHTTPRequestHandler +import CGIHTTPServer import os import sys @@ -315,6 +316,45 @@ class CGIHTTPServerTestCase(BaseTestCase finally: BaseTestCase.tearDown(self) + def test_url_collapse_path_split(self): + test_vectors = { + '': ('/', ''), + '..': IndexError, + '/.//..': IndexError, + '/': ('/', ''), + '//': ('/', ''), + '/\\': ('/', '\\'), + '/.//': ('/', ''), + 'cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), + '/cgi-bin/file1.py': ('/cgi-bin', 'file1.py'), + 'a': ('/', 'a'), + '/a': ('/', 'a'), + '//a': ('/', 'a'), + './a': ('/', 'a'), + './C:/': ('/C:', ''), + '/a/b': ('/a', 'b'), + '/a/b/': ('/a/b', ''), + '/a/b/c/..': ('/a/b', ''), + '/a/b/c/../d': ('/a/b', 'd'), + '/a/b/c/../d/e/../f': ('/a/b/d', 'f'), + '/a/b/c/../d/e/../../f': ('/a/b', 'f'), + '/a/b/c/../d/e/.././././..//f': ('/a/b', 'f'), + '../a/b/c/../d/e/.././././..//f': IndexError, + '/a/b/c/../d/e/../../../f': ('/a', 'f'), + '/a/b/c/../d/e/../../../../f': ('/', 'f'), + '/a/b/c/../d/e/../../../../../f': IndexError, + '/a/b/c/../d/e/../../../../f/..': ('/', ''), + } + for path, expected in test_vectors.iteritems(): + if isinstance(expected, type) and issubclass(expected, Exception): + self.assertRaises(expected, + CGIHTTPServer._url_collapse_path_split, path) + else: + actual = CGIHTTPServer._url_collapse_path_split(path) + self.assertEquals(expected, actual, + msg='path = %r\nGot: %r\nWanted: %r' % ( + path, actual, expected)) + def test_headers_and_content(self): res = self.request('/cgi-bin/file1.py') self.assertEquals(('Hello World\n', 'text/html', 200), \ @@ -339,6 +379,12 @@ class CGIHTTPServerTestCase(BaseTestCase self.assertEquals(('Hello World\n', 'text/html', 200), \ (res.read(), res.getheader('Content-type'), res.status)) + def test_no_leading_slash(self): + # http://bugs.python.org/issue2254 + res = self.request('cgi-bin/file1.py') + self.assertEquals(('Hello World\n', 'text/html', 200), + (res.read(), res.getheader('Content-type'), res.status)) + def test_main(verbose=None): try: ++++++ python-2.7-CVE-2011-1521-fileurl.patch ++++++ # HG changeset patch # User Guido van Rossum <gu...@python.org> # Date 1301428435 25200 # Node ID b2934d98dac1f7b13cc6cc280f06d1aec3f6e80d # Parent 1a5aab273332a7a379e35ed6f88400a110b5de0c# Parent 9eeda8e3a13f107a698f10b0a45ffc2c6bd710fb Merge issue 11662 from 2.6. diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py --- a/Lib/test/test_urllib.py +++ b/Lib/test/test_urllib.py @@ -161,6 +161,20 @@ Content-Type: text/html; charset=iso-885 finally: self.unfakehttp() + def test_invalid_redirect(self): + # urlopen() should raise IOError for many error codes. + self.fakehttp("""HTTP/1.1 302 Found +Date: Wed, 02 Jan 2008 03:03:54 GMT +Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e +Location: file:README +Connection: close +Content-Type: text/html; charset=iso-8859-1 +""") + try: + self.assertRaises(IOError, urllib.urlopen, "http://python.org/") + finally: + self.unfakehttp() + def test_empty_socket(self): # urlopen() raises IOError if the underlying socket does not send any # data. (#1680230) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -969,6 +969,27 @@ class HandlerTests(unittest.TestCase): self.assertEqual(count, urllib2.HTTPRedirectHandler.max_redirections) + def test_invalid_redirect(self): + from_url = "http://example.com/a.html" + valid_schemes = ['http', 'https', 'ftp'] + invalid_schemes = ['file', 'imap', 'ldap'] + schemeless_url = "example.com/b.html" + h = urllib2.HTTPRedirectHandler() + o = h.parent = MockOpener() + req = Request(from_url) + + for scheme in invalid_schemes: + invalid_url = scheme + '://' + schemeless_url + self.assertRaises(urllib2.HTTPError, h.http_error_302, + req, MockFile(), 302, "Security Loophole", + MockHeaders({"location": invalid_url})) + + for scheme in valid_schemes: + valid_url = scheme + '://' + schemeless_url + h.http_error_302(req, MockFile(), 302, "That's fine", + MockHeaders({"location": valid_url})) + self.assertEqual(o.req.get_full_url(), valid_url) + def test_cookie_redirect(self): # cookies shouldn't leak into redirected requests from cookielib import CookieJar diff --git a/Lib/urllib.py b/Lib/urllib.py --- a/Lib/urllib.py +++ b/Lib/urllib.py @@ -644,6 +644,18 @@ class FancyURLopener(URLopener): fp.close() # In case the server sent a relative URL, join with original: newurl = basejoin(self.type + ":" + url, newurl) + + # For security reasons we do not allow redirects to protocols + # other than HTTP, HTTPS or FTP. + newurl_lower = newurl.lower() + if not (newurl_lower.startswith('http://') or + newurl_lower.startswith('https://') or + newurl_lower.startswith('ftp://')): + raise IOError('redirect error', errcode, + errmsg + " - Redirection to url '%s' is not allowed" % + newurl, + headers) + return self.open(newurl) def http_error_301(self, url, fp, errcode, errmsg, headers, data=None): diff --git a/Lib/urllib2.py b/Lib/urllib2.py --- a/Lib/urllib2.py +++ b/Lib/urllib2.py @@ -578,6 +578,17 @@ class HTTPRedirectHandler(BaseHandler): newurl = urlparse.urljoin(req.get_full_url(), newurl) + # For security reasons we do not allow redirects to protocols + # other than HTTP, HTTPS or FTP. + newurl_lower = newurl.lower() + if not (newurl_lower.startswith('http://') or + newurl_lower.startswith('https://') or + newurl_lower.startswith('ftp://')): + raise HTTPError(newurl, code, + msg + " - Redirection to url '%s' is not allowed" % + newurl, + headers, fp) + # XXX Probably want to forget about the state of the current # request, although that might interact poorly with other # handlers that also use handler-specific request attributes ++++++ python-2.7-fix-parallel-make.patch ++++++ diff -up Python-2.7/Makefile.pre.in.fix-parallel-make Python-2.7/Makefile.pre.in --- Python-2.7/Makefile.pre.in.fix-parallel-make 2010-07-22 15:01:39.567996932 -0400 +++ Python-2.7/Makefile.pre.in 2010-07-22 15:47:02.437998509 -0400 @@ -207,6 +207,7 @@ SIGNAL_OBJS= @SIGNAL_OBJS@ ########################################################################## # Grammar +GRAMMAR_STAMP= $(srcdir)/grammar-stamp GRAMMAR_H= $(srcdir)/Include/graminit.h GRAMMAR_C= $(srcdir)/Python/graminit.c GRAMMAR_INPUT= $(srcdir)/Grammar/Grammar @@ -530,10 +531,24 @@ Modules/getpath.o: $(srcdir)/Modules/get Modules/python.o: $(srcdir)/Modules/python.c $(MAINCC) -c $(PY_CFLAGS) -o $@ $(srcdir)/Modules/python.c +# GNU "make" interprets rules with two dependents as two copies of the rule. +# +# In a parallel build this can lead to pgen being run twice, once for each of +# GRAMMAR_H and GRAMMAR_C, leading to race conditions in which the compiler +# reads a partially-overwritten copy of one of these files, leading to syntax +# errors (or linker errors if the fragment happens to be syntactically valid C) +# +# See http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html +# for more information +# +# Introduce ".grammar-stamp" as a contrived single output from PGEN to avoid +# this: +$(GRAMMAR_H) $(GRAMMAR_C): $(GRAMMAR_STAMP) -$(GRAMMAR_H) $(GRAMMAR_C): $(PGEN) $(GRAMMAR_INPUT) +$(GRAMMAR_STAMP): $(PGEN) $(GRAMMAR_INPUT) -@$(INSTALL) -d Include -$(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) + touch $(GRAMMAR_STAMP) $(PGEN): $(PGENOBJS) $(CC) $(OPT) $(LDFLAGS) $(PGENOBJS) $(LIBS) -o $(PGEN) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org