summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/bug-6994_vert-expiration-check-problem1
-rw-r--r--src/leap/common/certs.py17
-rw-r--r--src/leap/common/testing/leaptest_combined_keycert.pem127
-rw-r--r--src/leap/common/tests/test_certs.py97
4 files changed, 234 insertions, 8 deletions
diff --git a/changes/bug-6994_vert-expiration-check-problem b/changes/bug-6994_vert-expiration-check-problem
new file mode 100644
index 0000000..603e722
--- /dev/null
+++ b/changes/bug-6994_vert-expiration-check-problem
@@ -0,0 +1 @@
+- Fix time comparison between local and UTC times that caused the VPN certificates not being correctly downloaded on time. Closes #6994.
diff --git a/src/leap/common/certs.py b/src/leap/common/certs.py
index 4fe563b..db513f6 100644
--- a/src/leap/common/certs.py
+++ b/src/leap/common/certs.py
@@ -128,22 +128,23 @@ def is_valid_pemfile(cert):
return can_load_cert_and_pkey(cert)
-def get_cert_time_boundaries(certfile):
+def get_cert_time_boundaries(certdata):
"""
- Returns the time boundaries for the certificate saved in certfile
+ Return the time boundaries for the given certificate.
+ The returned values are UTC/GMT time.struct_time objects
- :param certfile: path to certificate
- :type certfile: str
+ :param certdata: the certificate contents
+ :type certdata: str
:rtype: tuple (from, to)
"""
- cert = get_cert_from_string(certfile)
+ cert = get_cert_from_string(certdata)
leap_assert(cert, 'There was a problem loading the certificate')
fromts, tots = (cert.get_notBefore(), cert.get_notAfter())
- from_, to_ = map(
- lambda ts: time.gmtime(time.mktime(dateparse(ts).timetuple())),
- (fromts, tots))
+ from_ = dateparse(fromts).timetuple()
+ to_ = dateparse(tots).timetuple()
+
return from_, to_
diff --git a/src/leap/common/testing/leaptest_combined_keycert.pem b/src/leap/common/testing/leaptest_combined_keycert.pem
new file mode 100644
index 0000000..f1e0fb2
--- /dev/null
+++ b/src/leap/common/testing/leaptest_combined_keycert.pem
@@ -0,0 +1,127 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAT67c8y4ORa6o
+/gor3gAouJI6W6R7YlPzzh4uaba4YhqgAEZzcZ7S589CqON8Eo8G2tQvh+ZSaNmP
+idFDjFxfpb1sBMb9Nu720s0V8UMxzCDh7oyePZGdKP+F04+MkB0eHWSObBrzsjsj
+KVsD/5fUeLbd1SdK1C2cKzsoRQ+GVEyMJeiISFlV05fxdAZSybPcwH+3aiVX+7cM
+9ek8bufIeqrAfZVdvO/2Fuv6WfR2MEe32XO/9gj02XSGWd6sPXMn/lflKvNNKEWC
+UWdqTArGi0CqQ4D+Q73ruUIthCJr+7LWK+7QKG980a1RR7GZJvs3skhUDh3eua2u
+ICPiqQLlAgMBAAECggEBAKJr6j0UagaF1dFG1eJc2neKA36kXdQTpOIaaKU8haVO
+vjv6X4YrJT/tpsAfEhp9Ni1M7r7CIcXiZjVz6bkKOA5UVhqAImxEVClEuw/YN688
+P11yc3NGftBkiwNFPk0yflUr7/zV0yGVm5rD1+oVme9KkO/kkg4CDA+E9664PTdu
+S4NVvL6OgHUG2nucqIz0kzUBapo7okIkvggfldeDYF47rn/e0VikNpKkMzoCzWs+
+3ryzldfigwg18rE2nltQYk/Mi+H30iNTNEonLjs9YbiDPn8iy5SZ7xY4lAO1Urev
+skdY04hmkOzh9JEETHeTj1LUIw7tfRdS3X6B+19gkCECgYEA+41UOLBb0ZHsGjsA
+aZBtI4g8mvGTOFe/Az7Jm0404z6e8AIe4NeSJoJ6oV6WG2BmKvqTViYT2QnmauHA
+WB1xJ5fH3PK7/LjICI2QE247E294+g5p1KYysALc2fChfJNpdfETzWJAUSSBFqxb
+amCDZ4Gc8S/V44fEkJKPLuAvxL0CgYEAw7YyGsEX+lDGzumFQY4wz20+Cyvilnx0
+xoFGQ85RSprZttU64PID/u1HD9/Nv4lGcBDcTTtrmOEk9x51YzttrsPF9sn+Wj0y
+eahuR32Qc1652Y7fAKgN2vIZRFBcGpAsemcoqmYFRMImX60G0areKaclooimTbJA
+Si52P4IKnUkCgYAI+07ah1F/9hncBedJ3aJH9oFTdvSuulNTplZEeVJiGsZKA4le
+tdO+FEKUqG/rolGDj1bbaJik0zmq70yS2NpFc6HrPa+Aoohh5cwTJYhudTh4lTMq
+KJT+u9tu3KynagwF7gmq96scOpVxXc4VykRm2bXk1rRoX1yhXNpH7jFGcQKBgCn/
+v2DebzbYftGIa4BV80OQPfBHyqhgrO6sb1e9vtQzxuTlfW0ogpMCeG1/qbegzeze
+sWghiEWWi0g80RQqfK80dBcx4dObrmlNK91LpOQdP+TgNBr/9Xk22xU96YYJyoG6
+AZAPtLG8uF9v0jbMZECsDfeDO60Qw5snvViDn6OBAoGACAbbQCbuh0cduDVwn0uz
+8XDyRTKDhOsJ3p6UB1TjwvbLeoPI93Dv1gpEeoqELtCu+ZXr3+/i/IbwrxucrFNn
+L/s+4zR2mlEAxBdtCFsH/Qf7+iYpBFSo4YReXz3xR+EVTmswzodJCbtF74oQSr6o
+7d56Rd/5k2UkFeXnlGOLyAc=
+-----END PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 4 (0x4)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=US, ST=CA, L=Cyberspace, O=LEAP Encryption Access Project, OU=cyberspace, CN=tests-leap.se/name=tests-leap/emailAddress=tests@leap.se
+ Validity
+ Not Before: Sep 3 17:52:16 2013 GMT
+ Not After : Sep 1 17:52:16 2023 GMT
+ Subject: C=US, ST=CA, L=Cyberspace, O=LEAP Encryption Access Project, OU=cyberspace, CN=localhost/name=tests-leap/emailAddress=tests@leap.se
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (2048 bit)
+ Modulus:
+ 00:c0:4f:ae:dc:f3:2e:0e:45:ae:a8:fe:0a:2b:de:
+ 00:28:b8:92:3a:5b:a4:7b:62:53:f3:ce:1e:2e:69:
+ b6:b8:62:1a:a0:00:46:73:71:9e:d2:e7:cf:42:a8:
+ e3:7c:12:8f:06:da:d4:2f:87:e6:52:68:d9:8f:89:
+ d1:43:8c:5c:5f:a5:bd:6c:04:c6:fd:36:ee:f6:d2:
+ cd:15:f1:43:31:cc:20:e1:ee:8c:9e:3d:91:9d:28:
+ ff:85:d3:8f:8c:90:1d:1e:1d:64:8e:6c:1a:f3:b2:
+ 3b:23:29:5b:03:ff:97:d4:78:b6:dd:d5:27:4a:d4:
+ 2d:9c:2b:3b:28:45:0f:86:54:4c:8c:25:e8:88:48:
+ 59:55:d3:97:f1:74:06:52:c9:b3:dc:c0:7f:b7:6a:
+ 25:57:fb:b7:0c:f5:e9:3c:6e:e7:c8:7a:aa:c0:7d:
+ 95:5d:bc:ef:f6:16:eb:fa:59:f4:76:30:47:b7:d9:
+ 73:bf:f6:08:f4:d9:74:86:59:de:ac:3d:73:27:fe:
+ 57:e5:2a:f3:4d:28:45:82:51:67:6a:4c:0a:c6:8b:
+ 40:aa:43:80:fe:43:bd:eb:b9:42:2d:84:22:6b:fb:
+ b2:d6:2b:ee:d0:28:6f:7c:d1:ad:51:47:b1:99:26:
+ fb:37:b2:48:54:0e:1d:de:b9:ad:ae:20:23:e2:a9:
+ 02:e5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Cert Type:
+ SSL Server
+ Netscape Comment:
+ Easy-RSA Generated Server Certificate
+ X509v3 Subject Key Identifier:
+ 51:92:B6:A3:D7:D6:EC:8F:FC:16:C5:D4:0F:87:CC:EA:5C:7C:17:81
+ X509v3 Authority Key Identifier:
+ keyid:36:19:70:96:A9:5C:FE:A3:82:0F:79:95:31:52:2B:4A:41:BD:81:CB
+ DirName:/C=US/ST=CA/L=Cyberspace/O=LEAP Encryption Access Project/OU=cyberspace/CN=tests-leap.se/name=tests-leap/emailAddress=tests@leap.se
+ serial:8B:BF:41:63:1E:10:6A:EC
+
+ X509v3 Extended Key Usage:
+ TLS Web Server Authentication
+ X509v3 Key Usage:
+ Digital Signature, Key Encipherment
+ Signature Algorithm: sha1WithRSAEncryption
+ 88:d9:35:e0:d9:fa:fd:6b:57:e2:4d:f6:ef:91:6f:56:a6:2b:
+ 1a:1e:ec:8f:b0:18:e3:ec:ca:c9:1e:78:07:1d:0f:cf:fe:09:
+ 21:84:25:c4:27:ea:22:d7:48:53:73:ed:78:0f:42:5c:c7:f7:
+ 38:04:84:df:67:99:fd:75:6f:e8:dc:3b:91:ab:fa:c7:32:e5:
+ fd:3b:ce:de:7c:6a:df:39:46:1e:46:3a:4d:e1:e1:60:f3:bf:
+ aa:b2:0b:5d:ee:f2:0c:ee:82:7f:b5:02:75:04:47:d5:2b:c8:
+ e0:6d:6a:10:4a:ca:e0:c3:4f:ee:ff:15:71:37:f5:4d:95:38:
+ fe:a3:da:84:46:90:04:c2:61:86:a0:7f:e2:7d:62:46:6d:f6:
+ f8:90:51:88:c3:f2:8c:ca:b3:89:40:9f:6b:8b:33:65:e1:fd:
+ 0f:8b:d7:6a:93:dc:de:be:85:07:c7:d1:1d:b5:db:70:54:9f:
+ 95:d8:fb:11:f7:a7:e6:90:ba:9b:28:0e:3d:47:7a:63:6d:60:
+ 44:f6:96:aa:b6:a2:bc:0a:e5:25:c8:a2:74:91:54:95:bb:e2:
+ 09:01:56:73:6e:56:e8:6f:d6:a5:d8:18:96:c1:82:ef:2c:9e:
+ e2:4c:94:bc:00:71:5e:16:49:6b:e4:94:7a:d1:0c:2e:f4:19:
+ b2:2a:c2:b8
+-----BEGIN CERTIFICATE-----
+MIIFdDCCBFygAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBuDELMAkGA1UEBhMCVVMx
+CzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpDeWJlcnNwYWNlMScwJQYDVQQKEx5MRUFQ
+IEVuY3J5cHRpb24gQWNjZXNzIFByb2plY3QxEzARBgNVBAsTCmN5YmVyc3BhY2Ux
+FjAUBgNVBAMTDXRlc3RzLWxlYXAuc2UxEzARBgNVBCkTCnRlc3RzLWxlYXAxHDAa
+BgkqhkiG9w0BCQEWDXRlc3RzQGxlYXAuc2UwHhcNMTMwOTAzMTc1MjE2WhcNMjMw
+OTAxMTc1MjE2WjCBtDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQH
+EwpDeWJlcnNwYWNlMScwJQYDVQQKEx5MRUFQIEVuY3J5cHRpb24gQWNjZXNzIFBy
+b2plY3QxEzARBgNVBAsTCmN5YmVyc3BhY2UxEjAQBgNVBAMTCWxvY2FsaG9zdDET
+MBEGA1UEKRMKdGVzdHMtbGVhcDEcMBoGCSqGSIb3DQEJARYNdGVzdHNAbGVhcC5z
+ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMBPrtzzLg5Frqj+Cive
+ACi4kjpbpHtiU/POHi5ptrhiGqAARnNxntLnz0Ko43wSjwba1C+H5lJo2Y+J0UOM
+XF+lvWwExv027vbSzRXxQzHMIOHujJ49kZ0o/4XTj4yQHR4dZI5sGvOyOyMpWwP/
+l9R4tt3VJ0rULZwrOyhFD4ZUTIwl6IhIWVXTl/F0BlLJs9zAf7dqJVf7twz16Txu
+58h6qsB9lV287/YW6/pZ9HYwR7fZc7/2CPTZdIZZ3qw9cyf+V+Uq800oRYJRZ2pM
+CsaLQKpDgP5Dveu5Qi2EImv7stYr7tAob3zRrVFHsZkm+zeySFQOHd65ra4gI+Kp
+AuUCAwEAAaOCAYkwggGFMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEBBAQDAgZAMDQG
+CWCGSAGG+EIBDQQnFiVFYXN5LVJTQSBHZW5lcmF0ZWQgU2VydmVyIENlcnRpZmlj
+YXRlMB0GA1UdDgQWBBRRkraj19bsj/wWxdQPh8zqXHwXgTCB7QYDVR0jBIHlMIHi
+gBQ2GXCWqVz+o4IPeZUxUitKQb2By6GBvqSBuzCBuDELMAkGA1UEBhMCVVMxCzAJ
+BgNVBAgTAkNBMRMwEQYDVQQHEwpDeWJlcnNwYWNlMScwJQYDVQQKEx5MRUFQIEVu
+Y3J5cHRpb24gQWNjZXNzIFByb2plY3QxEzARBgNVBAsTCmN5YmVyc3BhY2UxFjAU
+BgNVBAMTDXRlc3RzLWxlYXAuc2UxEzARBgNVBCkTCnRlc3RzLWxlYXAxHDAaBgkq
+hkiG9w0BCQEWDXRlc3RzQGxlYXAuc2WCCQCLv0FjHhBq7DATBgNVHSUEDDAKBggr
+BgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEFBQADggEBAIjZNeDZ+v1r
+V+JN9u+Rb1amKxoe7I+wGOPsyskeeAcdD8/+CSGEJcQn6iLXSFNz7XgPQlzH9zgE
+hN9nmf11b+jcO5Gr+scy5f07zt58at85Rh5GOk3h4WDzv6qyC13u8gzugn+1AnUE
+R9UryOBtahBKyuDDT+7/FXE39U2VOP6j2oRGkATCYYagf+J9YkZt9viQUYjD8ozK
+s4lAn2uLM2Xh/Q+L12qT3N6+hQfH0R2123BUn5XY+xH3p+aQupsoDj1HemNtYET2
+lqq2orwK5SXIonSRVJW74gkBVnNuVuhv1qXYGJbBgu8snuJMlLwAcV4WSWvklHrR
+DC70GbIqwrg=
+-----END CERTIFICATE-----
diff --git a/src/leap/common/tests/test_certs.py b/src/leap/common/tests/test_certs.py
new file mode 100644
index 0000000..999071f
--- /dev/null
+++ b/src/leap/common/tests/test_certs.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+# test_certs.py
+# Copyright (C) 2013 LEAP
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+Tests for:
+ * leap/common/certs.py
+"""
+import os
+import time
+
+try:
+ import unittest2 as unittest
+except ImportError:
+ import unittest
+
+from leap.common import certs
+from leap.common.testing.basetest import BaseLeapTest
+
+TEST_CERT_PEM = os.path.join(
+ os.path.split(__file__)[0],
+ '..', 'testing', "leaptest_combined_keycert.pem")
+
+# Values from the test cert file:
+# Not Before: Sep 3 17:52:16 2013 GMT
+# Not After : Sep 1 17:52:16 2023 GMT
+CERT_NOT_BEFORE = (2013, 9, 3, 17, 52, 16, 1, 246, 0)
+CERT_NOT_AFTER = (2023, 9, 1, 17, 52, 16, 4, 244, 0)
+
+
+class CertsTest(BaseLeapTest):
+
+ def setUp(self):
+ pass
+
+ def tearDown(self):
+ pass
+
+ def test_should_redownload_if_no_cert(self):
+ self.assertTrue(certs.should_redownload(certfile=""))
+
+ def test_should_redownload_if_invalid_pem(self):
+ cert_path = self.get_tempfile('test_pem_file.pem')
+
+ with open(cert_path, 'w') as f:
+ f.write('this is some invalid data for the pem file')
+
+ self.assertTrue(certs.should_redownload(cert_path))
+
+ def test_should_redownload_if_before(self):
+ new_now = lambda: time.struct_time(CERT_NOT_BEFORE)
+ self.assertTrue(certs.should_redownload(TEST_CERT_PEM, now=new_now))
+
+ def test_should_redownload_if_after(self):
+ new_now = lambda: time.struct_time(CERT_NOT_AFTER)
+ self.assertTrue(certs.should_redownload(TEST_CERT_PEM, now=new_now))
+
+ def test_not_should_redownload(self):
+ self.assertFalse(certs.should_redownload(TEST_CERT_PEM))
+
+ def test_is_valid_pemfile(self):
+ with open(TEST_CERT_PEM) as f:
+ cert_data = f.read()
+
+ self.assertTrue(certs.is_valid_pemfile(cert_data))
+
+ def test_not_is_valid_pemfile(self):
+ cert_data = 'this is some invalid data for the pem file'
+
+ self.assertFalse(certs.is_valid_pemfile(cert_data))
+
+ def test_get_cert_time_boundaries(self):
+ """
+ This test ensures us that the returned values are returned in UTC/GMT.
+ """
+ with open(TEST_CERT_PEM) as f:
+ cert_data = f.read()
+
+ valid_from, valid_to = certs.get_cert_time_boundaries(cert_data)
+ self.assertEqual(tuple(valid_from), CERT_NOT_BEFORE)
+ self.assertEqual(tuple(valid_to), CERT_NOT_AFTER)
+
+
+if __name__ == "__main__":
+ unittest.main()