diff options
-rw-r--r-- | src/leap/bitmask/bonafide/_protocol.py | 4 | ||||
-rw-r--r-- | src/leap/bitmask/bonafide/config.py | 76 | ||||
-rw-r--r-- | src/leap/bitmask/bonafide/session.py | 2 | ||||
-rw-r--r-- | tests/integration/bonafide/cacert.pem | 30 | ||||
-rw-r--r-- | tests/integration/bonafide/leaptest_combined_keycert.pem | 127 | ||||
-rw-r--r-- | tests/integration/bonafide/leaptestscert.pem | 99 | ||||
-rw-r--r-- | tests/integration/bonafide/test_config.py | 146 |
7 files changed, 449 insertions, 35 deletions
diff --git a/src/leap/bitmask/bonafide/_protocol.py b/src/leap/bitmask/bonafide/_protocol.py index 0de5b7c..004359e 100644 --- a/src/leap/bitmask/bonafide/_protocol.py +++ b/src/leap/bitmask/bonafide/_protocol.py @@ -110,7 +110,7 @@ class BonafideProtocol(object): provider = config.Provider(provider_id, autoconf=autoconf) - def maybe_finish_provider_bootstrap(result, provider): + def maybe_finish_provider_bootstrap(result): session = self._get_session(provider, full_id, password) d = provider.download_services_config_with_auth(session) d.addCallback(lambda _: result) @@ -118,7 +118,7 @@ class BonafideProtocol(object): d = provider.callWhenReady( self._do_authenticate, provider, full_id, password) - d.addCallback(maybe_finish_provider_bootstrap, provider) + d.addCallback(maybe_finish_provider_bootstrap) return d def _do_authenticate(self, provider, full_id, password): diff --git a/src/leap/bitmask/bonafide/config.py b/src/leap/bitmask/bonafide/config.py index 5f3bff9..1e6e550 100644 --- a/src/leap/bitmask/bonafide/config.py +++ b/src/leap/bitmask/bonafide/config.py @@ -32,17 +32,16 @@ from cryptography.x509 import load_pem_x509_certificate from urlparse import urlparse from twisted.internet import defer, reactor -from twisted.internet.ssl import ClientContextFactory from twisted.logger import Logger -from twisted.web.client import Agent, downloadPage +from twisted.web.client import downloadPage -from leap.bitmask.bonafide._http import httpRequest from leap.bitmask.bonafide.provider import Discovery from leap.bitmask.bonafide.errors import NotConfiguredError, NetworkError from leap.common.check import leap_assert from leap.common.config import get_path_prefix as common_get_path_prefix from leap.common.files import mkdir_p +from leap.common.http import HTTPClient APPNAME = "bonafide" @@ -161,8 +160,6 @@ def delete_provider(domain): class Provider(object): - # TODO add validation - SERVICES_MAP = { 'openvpn': ['eip'], 'mx': ['soledad', 'smtp']} @@ -174,8 +171,7 @@ class Provider(object): stuck_bootstrap = defaultdict(None) def __init__(self, domain, autoconf=False, basedir=None, - check_certificate=True): - # TODO: I need a way to know if it was already configured + cert_path=None): if not basedir: basedir = os.path.join(_preffix, 'leap') self._basedir = os.path.expanduser(basedir) @@ -184,18 +180,13 @@ class Provider(object): self._provider_config = None is_configured = self.is_configured() - if not is_configured: - check_certificate = False - - if check_certificate: - self.contextFactory = None + if is_configured: + self._http = HTTPClient(self._get_ca_cert_path()) else: - # XXX we should do this only for the FIRST provider download. - # For the rest, we should pass the ca cert to the agent. - # That means that RIGHT AFTER DOWNLOADING provider_info, - # we should instantiate a new Agent... - self.contextFactory = WebClientContextFactory() - self._agent = Agent(reactor, self.contextFactory) + # TODO: we distribute our own cert bundle but it's too outdated, + # let's use for now the one from the system + # see: leap.common.ca_bundle.where() + self._http = HTTPClient(cert_path) self._load_provider_json() @@ -260,6 +251,8 @@ class Provider(object): ongoing = self.ongoing_bootstrap.get(domain) if ongoing: self.log.debug('Already bootstrapping this provider...') + self.ongoing_bootstrap[domain].addCallback( + self._reload_http_client) return self.first_bootstrap[self._domain] = defer.Deferred() @@ -270,10 +263,14 @@ class Provider(object): except defer.AlreadyCalledError: pass + def first_bootstrap_error(failure): + self.first_bootstrap[domain].errback(failure) + return failure + d = self.maybe_download_provider_info() d.addCallback(self.maybe_download_ca_cert) d.addCallback(self.validate_ca_cert) - d.addCallback(first_bootstrap_done) + d.addCallbacks(first_bootstrap_done, first_bootstrap_error) d.addCallback(self.maybe_download_services_config) self.ongoing_bootstrap[domain] = d @@ -311,7 +308,8 @@ class Provider(object): shutil.rmtree(folders) raise NetworkError(failure.getErrorMessage()) - d = downloadPage(uri, provider_json, method=met) + d = self._http.request(uri, method=met) + d.addCallback(_write_to_file, provider_json) d.addCallback(lambda _: self._load_provider_json()) d.addErrback(errback) return d @@ -326,20 +324,27 @@ class Provider(object): """ :rtype: deferred """ - - def errback(self, failure): - raise NetworkError(failure.getErrorMessage()) - path = self._get_ca_cert_path() if is_file(path): return defer.succeed('ca_cert_path_already_exists') + def errback(failure): + raise NetworkError(failure.getErrorMessage()) + uri = self._get_ca_cert_uri() mkdir_p(os.path.split(path)[0]) + + # We don't validate the TLS cert for this connection, + # just check the fingerprint of the ca.cert d = downloadPage(uri, path) + d.addCallback(self._reload_http_client) d.addErrback(errback) return d + def _reload_http_client(self, ret): + self._http = HTTPClient(self._get_ca_cert_path()) + return ret + def validate_ca_cert(self, ignored): expected = self._get_expected_ca_cert_fingerprint() algo, expectedfp = expected.split(':') @@ -377,6 +382,12 @@ class Provider(object): # UNAUTHENTICATED if we try to get the services # See: # https://leap.se/code/issues/7906 + def check_error(content): + c = json.loads(content) + if 'error' in c: + raise Exception(c['error']) + return content + def further_bootstrap_needs_auth(ignored): self.log.warn('Cannot download services config yet, need auth') pending_deferred = defer.Deferred() @@ -385,7 +396,9 @@ class Provider(object): uri, met, path = self._get_configs_download_params() - d = downloadPage(uri, path, method=met) + d = self._http.request(uri, method=met) + d.addCallback(check_error) + d.addCallback(_write_to_file, path) d.addCallback(lambda _: self._load_provider_json()) d.addCallback( lambda _: self._get_config_for_all_services(session=None)) @@ -553,13 +566,10 @@ class Provider(object): def _fetch_provider_configs_unauthenticated(self, uri, path): self.log.info('Downloading config for %s...' % uri) - d = downloadPage(uri, path, method='GET') + d = self._http.request(uri) + d.addCallback(_write_to_file, path) return d - def _http_request(self, *args, **kw): - # XXX pass if-modified-since header - return httpRequest(self._agent, *args, **kw) - class Record(object): def __init__(self, **kw): @@ -569,9 +579,9 @@ class Record(object): return self.__dict__ -class WebClientContextFactory(ClientContextFactory): - def getContext(self, hostname, port): - return ClientContextFactory.getContext(self) +def _write_to_file(content, path): + with open(path, 'w') as f: + f.write(content) if __name__ == '__main__': diff --git a/src/leap/bitmask/bonafide/session.py b/src/leap/bitmask/bonafide/session.py index 551bfa2..a05e209 100644 --- a/src/leap/bitmask/bonafide/session.py +++ b/src/leap/bitmask/bonafide/session.py @@ -169,6 +169,8 @@ class Session(object): return self._request(self._agent, uri, method=met) def _request(self, *args, **kw): + # TODO: we are not pinning the TLS cert of the API + # maybe we can use leap.common.http kw['token'] = self._token return httpRequest(*args, **kw) diff --git a/tests/integration/bonafide/cacert.pem b/tests/integration/bonafide/cacert.pem new file mode 100644 index 0000000..30c69c6 --- /dev/null +++ b/tests/integration/bonafide/cacert.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFGDCCBACgAwIBAgIJAIu/QWMeEGrsMA0GCSqGSIb3DQEBBQUAMIG4MQswCQYD +VQQGEwJVUzELMAkGA1UECBMCQ0ExEzARBgNVBAcTCkN5YmVyc3BhY2UxJzAlBgNV +BAoTHkxFQVAgRW5jcnlwdGlvbiBBY2Nlc3MgUHJvamVjdDETMBEGA1UECxMKY3li +ZXJzcGFjZTEWMBQGA1UEAxMNdGVzdHMtbGVhcC5zZTETMBEGA1UEKRMKdGVzdHMt +bGVhcDEcMBoGCSqGSIb3DQEJARYNdGVzdHNAbGVhcC5zZTAeFw0xMzA5MDMxNTA0 +MTFaFw0yMzA5MDExNTA0MTFaMIG4MQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex +EzARBgNVBAcTCkN5YmVyc3BhY2UxJzAlBgNVBAoTHkxFQVAgRW5jcnlwdGlvbiBB +Y2Nlc3MgUHJvamVjdDETMBEGA1UECxMKY3liZXJzcGFjZTEWMBQGA1UEAxMNdGVz +dHMtbGVhcC5zZTETMBEGA1UEKRMKdGVzdHMtbGVhcDEcMBoGCSqGSIb3DQEJARYN +dGVzdHNAbGVhcC5zZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ9R +L/azQ7jIzmB6+VEKFSdDw27DMq/aN87grNHqNAQiiU7b3hJLff9CAgMZhP92hB7X +Wwg/TN7IEMLUacP0EChRekI6VtpsNBlfb5g/8yq4kORWhniY99dnjbJaw2sGA3Oh +azySIvrKPxE/V393dmOQq+RFO4S+ytcq+rUILVFQX4lnFUHTyGGtpgMnB3smxJ8K +WPu9bZej0GXjeWgVb28HxoqMEJC+4lScRZT/p7VhWN0QmOW3SP4l65guvDStdTGY +z3uOFbGRuSRN9nHwTxe5COhyOa1TrEp89noHOGt3DRba4ZN4QUF3vX+c5JKaF6Ie +s7LajB3hSWe/8ifT9oMCAwEAAaOCASEwggEdMB0GA1UdDgQWBBQ2GXCWqVz+o4IP +eZUxUitKQb2ByzCB7QYDVR0jBIHlMIHigBQ2GXCWqVz+o4IPeZUxUitKQb2By6GB +vqSBuzCBuDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRMwEQYDVQQHEwpDeWJl +cnNwYWNlMScwJQYDVQQKEx5MRUFQIEVuY3J5cHRpb24gQWNjZXNzIFByb2plY3Qx +EzARBgNVBAsTCmN5YmVyc3BhY2UxFjAUBgNVBAMTDXRlc3RzLWxlYXAuc2UxEzAR +BgNVBCkTCnRlc3RzLWxlYXAxHDAaBgkqhkiG9w0BCQEWDXRlc3RzQGxlYXAuc2WC +CQCLv0FjHhBq7DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBVBey7 +ohxU/ir7g3In+uk3iyfZT+yhmjz1j6IWqbno+sc3CfCOiEgTRTphFTN2aP6pvigD +yKUBYZ0NRA5mAl3xopeT819DPkLgkacm4wugYKqV+60yrekmbEWsu/T5/jLWHN6s +QelIKdLklA9oivM1lCIqR+XV4A2MX3zwXdEmZp8QYiBAqLf49wgCLhSOrgXXUlb0 +EUMsyclHs9PN33YRd9qQiE0hwBwpcxxus/sonnMP2xDiDiCu6dnYC7BmzfYfgiS5 +7tfEGpKyuY+7J+etOzOKfkNA20ooVRvvpQ4rpcHulKwZE3yI0geW7YS2uL+p5ORO +twHvLcMPlAXUkXhS +-----END CERTIFICATE----- diff --git a/tests/integration/bonafide/leaptest_combined_keycert.pem b/tests/integration/bonafide/leaptest_combined_keycert.pem new file mode 100644 index 0000000..f1e0fb2 --- /dev/null +++ b/tests/integration/bonafide/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/tests/integration/bonafide/leaptestscert.pem b/tests/integration/bonafide/leaptestscert.pem new file mode 100644 index 0000000..7cb9265 --- /dev/null +++ b/tests/integration/bonafide/leaptestscert.pem @@ -0,0 +1,99 @@ +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/tests/integration/bonafide/test_config.py b/tests/integration/bonafide/test_config.py new file mode 100644 index 0000000..aeb2c84 --- /dev/null +++ b/tests/integration/bonafide/test_config.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +# test_config.py +# Copyright (C) 2015-2017 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/>. +import os.path + +from BaseHTTPServer import BaseHTTPRequestHandler +from twisted.internet import defer +from twisted.trial import unittest + +from leap.bitmask.bonafide.config import Provider +from leap.bitmask.bonafide.errors import NetworkError +from leap.common.testing.basetest import BaseLeapTest +from leap.common.testing.https_server import BaseHTTPSServerTestCase + + +class ConfigTest(BaseHTTPSServerTestCase, unittest.TestCase, BaseLeapTest): + + def setUp(self): + self.addr = Addr() + self.request_handler = request_handler(self.addr) + BaseHTTPSServerTestCase.setUp(self) + self.addr.host = 'localhost' + self.addr.port = self.PORT + + def test_bootstrap_self_sign_cert_fails(self): + home = os.path.join(self.home, 'self_sign') + os.mkdir(home) + provider = Provider(self.addr.domain, autoconf=True, basedir=home) + d = provider.callWhenMainConfigReady(lambda: "Cert was accepted") + return self.assertFailure(d, NetworkError) + + def test_bootstrap_pinned_cert(self): + cacert = os.path.join(os.path.dirname(__file__), + "cacert.pem") + home = os.path.join(self.home, 'pinned') + os.mkdir(home) + provider = Provider(self.addr.domain, autoconf=True, basedir=home, + cert_path=cacert) + + def check_provider(): + config = provider.config() + self.assertEqual(config["domain"], self.addr.host) + self.assertEqual(config["ca_cert_fingerprint"], + "SHA256: %s" % fingerprint) + + provider.callWhenMainConfigReady(check_provider) + return defer.gatherResults([ + provider.first_bootstrap[provider._domain], + provider.ongoing_bootstrap[provider._domain]]) + + +class Addr(object): + def __init__(self, host='localhost', port='4443'): + self.host = host + self.port = port + + @property + def domain(self): + return "%s:%s" % (self.host, self.port) + + +def request_handler(addr): + class RequestHandler(BaseHTTPRequestHandler): + def do_GET(self): + if self.path == '/provider.json': + body = provider_json % { + 'host': addr.host, + 'port': addr.port, + 'fingerprint': fingerprint + } + + elif self.path == '/ca.crt': + cacert = os.path.join(os.path.dirname(__file__), + "leaptestscert.pem") + with open(cacert, 'r') as f: + castr = f.read() + body = castr + + elif self.path == '/1/configs.json': + body = configs_json + + else: + body = '{"error": "not implemented"}' + + self.send_response(200) + self.send_header('Content-type', 'applicatino/json') + self.send_header('Content-Length', str(len(body))) + self.end_headers() + self.wfile.write(body) + + return RequestHandler + + +fingerprint = \ + "cd0131b3352b7a29c307156b24f09fe862b1f5a2e55be7cd888048b91770f220" +provider_json = """ +{ + "api_uri": "https://%(host)s:%(port)s", + "api_version": "1", + "ca_cert_fingerprint": "SHA256: %(fingerprint)s", + "ca_cert_uri": "https://%(host)s:%(port)s/ca.crt", + "default_language": "en", + "description": { + "en": "example" + }, + "domain": "%(host)s", + "enrollment_policy": "open", + "languages": [ + "en" + ], + "name": { + "en": "Bitmask" + }, + "service": { + "allow_anonymous": false, + "allow_free": true, + "allow_limited_bandwidth": false, + "allow_paid": false, + "allow_registration": true, + "allow_unlimited_bandwidth": true, + "bandwidth_limit": 102401, + "default_service_level": 1, + "levels": { + "1": { + "description": "hi.", + "name": "free" + } + } + }, + "services": [] +} +""" +configs_json = "{}" |