3 Fix information disclosure vulnerability reported in SA43463.
4 Patch taken from the Python SVN repository:
6 http://svn.python.org/view?view=revision&revision=71303
8 --- Lib/CGIHTTPServer.py.orig 2009-11-11 17:24:53.000000000 +0000
9 +++ Lib/CGIHTTPServer.py 2011-02-28 22:16:27.000000000 +0000
11 return SimpleHTTPServer.SimpleHTTPRequestHandler.send_head(self)
14 - """Test whether self.path corresponds to a CGI script,
15 - and return a boolean.
16 + """Test whether self.path corresponds to a CGI script.
18 - This function sets self.cgi_info to a tuple (dir, rest)
19 - when it returns True, where dir is the directory part before
20 - the CGI script name. Note that rest begins with a
21 - slash if it is not empty.
23 - The default implementation tests whether the path
24 - begins with one of the strings in the list
25 - self.cgi_directories (and the next character is a '/'
26 - or the end of the string).
27 + Returns True and updates the cgi_info attribute to the tuple
28 + (dir, rest) if self.path requires running a CGI script.
29 + Returns False otherwise.
31 + The default implementation tests whether the normalized url
32 + path begins with one of the strings in self.cgi_directories
33 + (and the next character is a '/' or the end of the string).
38 - for x in self.cgi_directories:
40 - if path[:i] == x and (not path[i:] or path[i] == '/'):
41 - self.cgi_info = path[:i], path[i+1:]
43 + splitpath = _url_collapse_path_split(self.path)
44 + if splitpath[0] in self.cgi_directories:
45 + self.cgi_info = splitpath
49 cgi_directories = ['/cgi-bin', '/htbin']
51 self.log_message("CGI script exited OK")
54 +# TODO(gregory.p.smith): Move this into an appropriate library.
55 +def _url_collapse_path_split(path):
57 + Given a URL path, remove extra '/'s and '.' path elements and collapse
58 + any '..' references.
60 + Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
62 + Returns: A tuple of (head, tail) where tail is everything after the final /
63 + and head is everything before it. Head will always start with a '/' and,
64 + if it contains anything else, never have a trailing '/'.
66 + Raises: IndexError if too many '..' occur within the path.
68 + # Similar to os.path.split(os.path.normpath(path)) but specific to URL
69 + # path semantics rather than local operating system semantics.
71 + for part in path.split('/'):
73 + path_parts.append('')
75 + path_parts.append(part)
76 + # Filter out blank non trailing parts before consuming the '..'.
77 + path_parts = [part for part in path_parts[:-1] if part] + path_parts[-1:]
79 + tail_part = path_parts.pop()
83 + for part in path_parts:
87 + head_parts.append(part)
88 + if tail_part and tail_part == '..':
91 + return ('/' + '/'.join(head_parts), tail_part)