Added CA verification for Fedora and OpenSUSE systems too
[zeroinstall.git] / zeroinstall / injector / _download_child.py
blob9d43a7eac5a04e239568b7e1b5e6c78f063abc91
1 # Copyright (C) 2011, Thomas Leonard
2 # See the README file for details, or visit http://0install.net.
4 import sys, os, socket, ssl
6 from zeroinstall import _
7 from zeroinstall.injector import download
9 import urllib2, httplib
11 for ca_bundle in ["/etc/ssl/certs/ca-certificates.crt", # Debian/Ubuntu/Arch Linux
12 "/etc/pki/tls/certs/ca-bundle.crt", # Fedora/RHEL
13 "/etc/ssl/ca-bundle.pem", # openSUSE/SLE (claimed)
14 "/var/lib/ca-certificates/ca-bundle.pem.new"]: # openSUSE (actual)
15 if os.path.exists(ca_bundle):
16 class ValidatingHTTPSConnection(httplib.HTTPSConnection):
17 def connect(self):
18 sock = socket.create_connection((self.host, self.port), self.timeout)
19 if self._tunnel_host:
20 self.sock = sock
21 self._tunnel()
22 self.sock = ssl.wrap_socket(sock, cert_reqs = ssl.CERT_REQUIRED, ca_certs = ca_bundle)
24 class ValidatingHTTPSHandler(urllib2.HTTPSHandler):
25 def https_open(self, req):
26 return self.do_open(self.getConnection, req)
28 def getConnection(self, host, timeout=300):
29 return ValidatingHTTPSConnection(host)
31 urlopener = urllib2.build_opener(ValidatingHTTPSHandler)
33 # Builds an opener that overrides the default HTTPS handler with our one
34 _my_urlopen = urllib2.build_opener(ValidatingHTTPSHandler()).open
35 break
36 else:
37 from logging import warn
38 warn("No root CA's found; security of HTTPS connections cannot be verified")
39 _my_urlopen = urllib2.urlopen
41 def download_in_thread(url, target_file, if_modified_since, notify_done):
42 try:
43 #print "Child downloading", url
44 if url.startswith('http:') or url.startswith('https:') or url.startswith('ftp:'):
45 req = urllib2.Request(url)
46 if url.startswith('http:') and if_modified_since:
47 req.add_header('If-Modified-Since', if_modified_since)
48 src = _my_urlopen(req)
49 else:
50 raise Exception(_('Unsupported URL protocol in: %s') % url)
52 try:
53 sock = src.fp._sock
54 except AttributeError:
55 sock = src.fp.fp._sock # Python 2.5 on FreeBSD
56 while True:
57 data = sock.recv(256)
58 if not data: break
59 target_file.write(data)
60 target_file.flush()
62 notify_done(download.RESULT_OK)
63 except (urllib2.HTTPError, urllib2.URLError, httplib.HTTPException) as ex:
64 if isinstance(ex, urllib2.HTTPError) and ex.code == 304: # Not modified
65 notify_done(download.RESULT_NOT_MODIFIED)
66 else:
67 #print >>sys.stderr, "Error downloading '" + url + "': " + (str(ex) or str(ex.__class__.__name__))
68 __, ex, tb = sys.exc_info()
69 notify_done(download.RESULT_FAILED, (download.DownloadError(unicode(ex)), tb))
70 except Exception as ex:
71 __, ex, tb = sys.exc_info()
72 notify_done(download.RESULT_FAILED, (ex, tb))