Merge lp:~dobey/ubuntu-sso-client/update-13-10 into lp:ubuntu-sso-client/stable-13-10

Proposed by dobey
Status: Merged
Approved by: dobey
Approved revision: no longer in the source branch.
Merged at revision: 1031
Proposed branch: lp:~dobey/ubuntu-sso-client/update-13-10
Merge into: lp:ubuntu-sso-client/stable-13-10
Diff against target: 339 lines (+193/-10)
8 files modified
data/UbuntuOne-Go_Daddy_CA.pem (+29/-0)
data/UbuntuOne-Go_Daddy_Class_2_CA.pem (+25/-0)
data/UbuntuOne-ValiCert_Class_2_VA.pem (+18/-0)
setup.py (+11/-10)
ubuntu_sso/utils/__init__.py (+25/-0)
ubuntu_sso/utils/tests/test_common.py (+44/-0)
ubuntu_sso/utils/webclient/qtnetwork.py (+24/-0)
ubuntu_sso/utils/webclient/tests/test_qtnetwork.py (+17/-0)
To merge this branch: bzr merge lp:~dobey/ubuntu-sso-client/update-13-10
Reviewer Review Type Date Requested Status
Mike McCracken (community) Approve
Review via email: mp+166380@code.launchpad.net

Commit message

[Brian Curtin]

    - Set SSL configuration with bundled certificates for all WebClient requests.

To post a comment you must log in.
Revision history for this message
Mike McCracken (mikemc) :
review: Approve
1031. By Brian Curtin

[Brian Curtin]

    - Set SSL configuration with bundled certificates for all WebClient requests.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'data/UbuntuOne-Go_Daddy_CA.pem'
2--- data/UbuntuOne-Go_Daddy_CA.pem 1970-01-01 00:00:00 +0000
3+++ data/UbuntuOne-Go_Daddy_CA.pem 2013-05-29 20:29:29 +0000
4@@ -0,0 +1,29 @@
5+-----BEGIN CERTIFICATE-----
6+MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
7+ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
8+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
9+MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
10+QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
11+b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
12+b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
13+YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
14+AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
15+KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
16+VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
17+SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
18+cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
19+6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
20+MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
21+kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
22+BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
23+BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
24+c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
25+AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
26+BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
27+OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
28+A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
29+0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
30+RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
31+qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
32+U+4=
33+-----END CERTIFICATE-----
34
35=== added file 'data/UbuntuOne-Go_Daddy_Class_2_CA.pem'
36--- data/UbuntuOne-Go_Daddy_Class_2_CA.pem 1970-01-01 00:00:00 +0000
37+++ data/UbuntuOne-Go_Daddy_Class_2_CA.pem 2013-05-29 20:29:29 +0000
38@@ -0,0 +1,25 @@
39+-----BEGIN CERTIFICATE-----
40+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJV
41+UzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQL
42+EyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
43+DTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMx
44+ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMo
45+R28gRGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAw
46+DQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d
47+/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9
48+S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32qRe3H3I2
49+TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVl
50+OARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFA
51+pMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44
52+dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLEsNKR1EwRcbNh
53+yz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2oatTj
54+oWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdy
55+b3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
56+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF
57+BQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYX
58+MP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
59+I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheab
60+IZ0KbIIOqPjCDPoQHmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzr
61+Tia2cyvk0/ZM/iZx4mERdEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBD
62+pqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/bvZ8=
63+-----END CERTIFICATE-----
64
65=== added file 'data/UbuntuOne-ValiCert_Class_2_VA.pem'
66--- data/UbuntuOne-ValiCert_Class_2_VA.pem 1970-01-01 00:00:00 +0000
67+++ data/UbuntuOne-ValiCert_Class_2_VA.pem 2013-05-29 20:29:29 +0000
68@@ -0,0 +1,18 @@
69+-----BEGIN CERTIFICATE-----
70+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
71+IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
72+BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
73+aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
74+9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
75+NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
76+azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
77+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
78+Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
79+cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
80+dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
81+WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
82+v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
83+UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
84+IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
85+W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
86+-----END CERTIFICATE-----
87
88=== modified file 'setup.py'
89--- setup.py 2013-04-03 18:50:39 +0000
90+++ setup.py 2013-05-29 20:29:29 +0000
91@@ -47,6 +47,8 @@
92
93 from distutils import log
94
95+from ubuntu_sso.utils import get_cert_dir
96+
97 PROJECT_NAME = 'ubuntu-sso-client'
98 VERSION = '4.3'
99
100@@ -285,14 +287,17 @@
101 cmdclass['build_i18n'] = dummy_build_i18n
102
103
104-def setup_windows():
105- """Provide the required info to setup the project on windows."""
106+data_files = [(get_cert_dir(),
107+ ['data/UbuntuOne-Go_Daddy_CA.pem',
108+ 'data/UbuntuOne-ValiCert_Class_2_VA.pem',
109+ 'data/UbuntuOne-Go_Daddy_Class_2_CA.pem'])]
110+
111+if sys.platform == 'win32':
112 set_py2exe_paths()
113- _data_files = []
114 # for PyQt, see http://www.py2exe.org/index.cgi/Py2exeAndPyQt
115 _includes = ['sip', 'email', 'ubuntu_sso.qt.gui',
116 'ubuntu_sso.qt.controllers', 'PyQt4.QtNetwork', 'PIL']
117- _extra = {
118+ extra = {
119 'options': {
120 'py2exe': {
121 'bundle_files': 1,
122@@ -306,15 +311,11 @@
123 'console': sso_executables,
124 'zipfile': None,
125 }
126- return _data_files, _extra
127-
128-if sys.platform == 'win32':
129- data_files, extra = setup_windows()
130 else:
131- data_files = [
132+ data_files.extend([
133 ('lib/ubuntu-sso-client', sso_executables),
134 ('share/dbus-1/services', ['data/com.ubuntu.sso.service']),
135- ]
136+ ])
137 extra = {}
138
139 DistUtilsExtra.auto.setup(
140
141=== modified file 'ubuntu_sso/utils/__init__.py'
142--- ubuntu_sso/utils/__init__.py 2012-10-23 14:17:58 +0000
143+++ ubuntu_sso/utils/__init__.py 2013-05-29 20:29:29 +0000
144@@ -33,6 +33,7 @@
145 import os
146 import sys
147
148+from dirspec.basedir import load_config_paths
149 from dirspec.utils import get_program_path
150
151 from twisted.internet import defer
152@@ -141,6 +142,30 @@
153 return cmd_args
154
155
156+def get_cert_dir():
157+ """Return directory containing certificate files."""
158+
159+ if getattr(sys, "frozen", None) is not None:
160+ if sys.platform == "win32":
161+ ssl_cert_location = list(load_config_paths(
162+ "ubuntuone"))[1]
163+ elif sys.platform == "darwin":
164+ main_app_dir = "".join(__file__.partition(".app")[:-1])
165+ main_app_resources_dir = os.path.join(main_app_dir,
166+ "Contents",
167+ "Resources")
168+ ssl_cert_location = main_app_resources_dir
169+ elif any(plat in sys.platform for plat in ("win32", "darwin")):
170+ pkg_dir = os.path.dirname(__file__)
171+ src_tree_path = os.path.dirname(os.path.dirname(pkg_dir))
172+ ssl_cert_location = os.path.join(src_tree_path,
173+ "data")
174+ else:
175+ ssl_cert_location = '/etc/ssl/certs'
176+
177+ return ssl_cert_location
178+
179+
180 @defer.inlineCallbacks
181 def ping_url(url, email, credentials):
182 """Ping the 'url' with the 'email' attached to it.
183
184=== modified file 'ubuntu_sso/utils/tests/test_common.py'
185--- ubuntu_sso/utils/tests/test_common.py 2013-02-11 21:52:34 +0000
186+++ ubuntu_sso/utils/tests/test_common.py 2013-05-29 20:29:29 +0000
187@@ -32,6 +32,7 @@
188
189 import logging
190 import sys
191+import os
192
193 from twisted.internet import defer
194 from twisted.web import resource
195@@ -167,6 +168,49 @@
196 self.assertEqual(expected, result)
197
198
199+class GetCertDirTestCase(TestCase):
200+ """Test determining the cert location."""
201+
202+ @defer.inlineCallbacks
203+ def setUp(self):
204+ yield super(GetCertDirTestCase, self).setUp()
205+
206+ def test_win(self):
207+ """Test geting a path when Common AppData is defined."""
208+ self.patch(utils, "__file__",
209+ os.path.join("path", "to", "ubuntu_sso",
210+ "utils", "__init__.py"))
211+ self.patch(sys, "platform", "win32")
212+ path = utils.get_cert_dir()
213+ self.assertEqual(path, os.path.join("path", "to", "data"))
214+
215+ def test_darwin_frozen(self):
216+ """Test that we get a path with .app in it on frozen darwin."""
217+ self.patch(sys, "platform", "darwin")
218+ sys.frozen = "macosx-app"
219+ self.addCleanup(delattr, sys, "frozen")
220+ self.patch(utils, "__file__",
221+ os.path.join("path", "to", "Main.app", "ignore"))
222+ path = utils.get_cert_dir()
223+ self.assertEqual(path, os.path.join("path", "to", "Main.app",
224+ "Contents", "Resources"))
225+
226+ def test_darwin_unfrozen(self):
227+ """Test that we get a source-relative path on unfrozen darwin."""
228+ self.patch(sys, "platform", "darwin")
229+ self.patch(utils, "__file__",
230+ os.path.join("path", "to", "ubuntuone",
231+ "utils", "__init__.py"))
232+ path = utils.get_cert_dir()
233+ self.assertEqual(path, os.path.join("path", "to", "data"))
234+
235+ def test_linux(self):
236+ """Test that linux gets the right path."""
237+ self.patch(sys, "platform", "linux2")
238+ path = utils.get_cert_dir()
239+ self.assertEqual(path, "/etc/ssl/certs")
240+
241+
242 class RootResource(resource.Resource):
243 """A root resource that logs the number of calls."""
244
245
246=== modified file 'ubuntu_sso/utils/webclient/qtnetwork.py'
247--- ubuntu_sso/utils/webclient/qtnetwork.py 2013-03-28 21:50:02 +0000
248+++ ubuntu_sso/utils/webclient/qtnetwork.py 2013-05-29 20:29:29 +0000
249@@ -30,6 +30,8 @@
250
251 from __future__ import unicode_literals
252
253+import glob
254+import os
255 import sys
256 from io import StringIO
257
258@@ -47,10 +49,12 @@
259 QNetworkReply,
260 QNetworkRequest,
261 QSslCertificate,
262+ QSslConfiguration,
263 )
264 from twisted.internet import defer
265
266 from ubuntu_sso.logger import setup_logging
267+from ubuntu_sso.utils import get_cert_dir
268 from ubuntu_sso.utils.webclient.common import (
269 BaseWebClient,
270 HeaderDict,
271@@ -102,6 +106,25 @@
272 self.proxy_retry = False
273 self.setup_proxy()
274
275+ # Apply our local certificates as the SSL configuration to be used
276+ # for all QNetworkRequest calls.
277+ self.ssl_config = QSslConfiguration.defaultConfiguration()
278+ ca_certs = self.ssl_config.caCertificates()
279+ try:
280+ for path in glob.glob(os.path.join(get_cert_dir(),
281+ "UbuntuOne*.pem")):
282+ with open(path) as f:
283+ cert = QSslCertificate(f.read())
284+ if cert.isValid():
285+ ca_certs.append(cert)
286+ else:
287+ logger.error("invalid certificate: {}".format(path))
288+ except (IndexError, IOError) as err:
289+ raise WebClientError(
290+ "Unable to configure SSL certificates: {}".format(err))
291+
292+ self.ssl_config.setCaCertificates(ca_certs)
293+
294 def _set_proxy(self, proxy):
295 """Set the proxy to be used."""
296 QNetworkProxy.setApplicationProxy(proxy)
297@@ -157,6 +180,7 @@
298 """Return a deferred that will be fired with a Response object."""
299 uri = self.iri_to_uri(iri)
300 request = QNetworkRequest(QUrl(uri))
301+ request.setSslConfiguration(self.ssl_config)
302 headers = yield self.build_request_headers(uri, method, extra_headers,
303 oauth_credentials)
304
305
306=== modified file 'ubuntu_sso/utils/webclient/tests/test_qtnetwork.py'
307--- ubuntu_sso/utils/webclient/tests/test_qtnetwork.py 2012-12-14 22:06:47 +0000
308+++ ubuntu_sso/utils/webclient/tests/test_qtnetwork.py 2013-05-29 20:29:29 +0000
309@@ -47,6 +47,8 @@
310 self.settings = dict(https=dict(username='user', password='pasword'))
311 self.patch(qtnetwork.gsettings, 'get_proxy_settings',
312 lambda: self.settings)
313+ self.patch(qtnetwork, "get_cert_dir", lambda: "")
314+ self.patch(qtnetwork.glob, "glob", lambda dir: [])
315
316 self.proxy = None
317
318@@ -69,6 +71,21 @@
319 def _clean_webclient_instance(self):
320 """Set the webclient not to have a proxy."""
321 qtnetwork.WebClient.proxy_instance = None
322+
323+ def test_setup_no_certs(self):
324+ # Ensure WebClient can start even if it finds no certs.
325+ # It may or may not end up working depending on the certs actually
326+ # being in the system, but not having them locally shouldn't prevent
327+ # startup.
328+ qtnetwork.WebClient()
329+
330+ def test_setup_unreadable_cert(self):
331+ # If for some reason a cert of our own is found but can't be read,
332+ # make sure we raise WebClientError.
333+ # glob only returns paths that actually exist, but we fake this by
334+ # passing something that can't be opened.
335+ self.patch(qtnetwork.glob, "glob", lambda dir: ["asdfasdfasdf"])
336+ self.assertRaises(qtnetwork.WebClientError, qtnetwork.WebClient)
337
338
339 class SetupLinuxProxyTestCase(SetupProxyTestCase):

Subscribers

People subscribed via source and target branches

to all changes: