Return-Path: X-Original-To: apmail-qpid-commits-archive@www.apache.org Delivered-To: apmail-qpid-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id ED75B17BA4 for ; Thu, 18 Jun 2015 20:15:07 +0000 (UTC) Received: (qmail 35112 invoked by uid 500); 18 Jun 2015 20:15:07 -0000 Delivered-To: apmail-qpid-commits-archive@qpid.apache.org Received: (qmail 35058 invoked by uid 500); 18 Jun 2015 20:15:07 -0000 Mailing-List: contact commits-help@qpid.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@qpid.apache.org Delivered-To: mailing list commits@qpid.apache.org Received: (qmail 34754 invoked by uid 99); 18 Jun 2015 20:15:07 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Jun 2015 20:15:07 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 8B699E3CAA; Thu, 18 Jun 2015 20:15:07 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: kgiusti@apache.org To: commits@qpid.apache.org Date: Thu, 18 Jun 2015 20:15:26 -0000 Message-Id: <44f15f54345743aab436d910683b1c2a@git.apache.org> In-Reply-To: <1083935ed35643a0a00ef95a4b0b9f42@git.apache.org> References: <1083935ed35643a0a00ef95a4b0b9f42@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [21/50] [abbrv] qpid-proton git commit: PROTON-909: Tests for Cyrus SASL mechs PROTON-909: Tests for Cyrus SASL mechs Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/990b11e8 Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/990b11e8 Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/990b11e8 Branch: refs/heads/kgiusti-python3 Commit: 990b11e8a3e3b7a63c891b42e22ea3d180278e55 Parents: e55fe32 Author: Andrew Stitcher Authored: Tue Jun 2 03:26:44 2015 -0400 Committer: Andrew Stitcher Committed: Thu Jun 11 16:20:28 2015 -0400 ---------------------------------------------------------------------- proton-j/src/main/resources/csasl.py | 16 ++ tests/python/proton_tests/sasl.py | 248 +++++++++++++++++++++++++++++- 2 files changed, 258 insertions(+), 6 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/990b11e8/proton-j/src/main/resources/csasl.py ---------------------------------------------------------------------- diff --git a/proton-j/src/main/resources/csasl.py b/proton-j/src/main/resources/csasl.py index 32f8039..b36b104 100644 --- a/proton-j/src/main/resources/csasl.py +++ b/proton-j/src/main/resources/csasl.py @@ -62,6 +62,22 @@ SASL_OUTCOMES_J2P = { def pn_transport_require_auth(transport, require): transport.impl.sasl().allowSkip(not require) +# TODO: Placeholders +def pn_transport_is_authenticated(transport): + raise Skipped('Not supported in Proton-J') + +def pn_transport_is_encrypted(transport): + raise Skipped('Not supported in Proton-J') + +def pn_transport_get_user(transport): + raise Skipped('Not supported in Proton-J') + +def pn_connection_set_user(connection, user): + pass + +def pn_connection_set_password(connection, password): + pass + def pn_sasl_allowed_mechs(sasl, mechs): sasl.setMechanisms(*mechs.split()) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/990b11e8/tests/python/proton_tests/sasl.py ---------------------------------------------------------------------- diff --git a/tests/python/proton_tests/sasl.py b/tests/python/proton_tests/sasl.py index 68fb6e3..91b3e69 100644 --- a/tests/python/proton_tests/sasl.py +++ b/tests/python/proton_tests/sasl.py @@ -18,9 +18,69 @@ # import sys, os, common +from string import Template +import subprocess + from proton import * from common import pump, Skipped +from cproton import * + +def _sslCertpath(file): + """ Return the full path to the certificate,keyfile, etc. + """ + return os.path.join(os.path.dirname(__file__), + "ssl_db/%s" % file) + +def _cyrusSetup(conf_dir): + """Write out simple SASL config + """ + t = Template("""sasldb_path: ${db} +mech_list: EXTERNAL DIGEST-MD5 SCRAM-SHA-1 CRAM-MD5 PLAIN ANONYMOUS +""") + subprocess.call(args=['rm','-rf',conf_dir]) + os.mkdir(conf_dir) + db = os.path.abspath(os.path.join(conf_dir,'proton.sasldb')) + conf = os.path.abspath(os.path.join(conf_dir,'proton.conf')) + f = open(conf, 'w') + f.write(t.substitute(db=db)) + f.close() + + cmd = Template("echo password | saslpasswd2 -c -p -f ${db} -u proton user").substitute(db=db) + subprocess.call(args=cmd, shell=True) + +def _testSaslMech(self, mech, clientUser='user@proton', authUser='user@proton', encrypted=False, authenticated=True): + self.s1.allowed_mechs(mech) + self.c1.open() + + pump(self.t1, self.t2, 1024) + + if encrypted: + assert self.t2.encrypted == encrypted + assert self.t1.encrypted == encrypted + assert self.t2.authenticated == authenticated + assert self.t1.authenticated == authenticated + if authenticated: + # Server + assert self.t2.user == authUser + assert self.s2.user == authUser + assert self.s2.mech == mech.strip() + assert self.s2.outcome == SASL.OK + # Client + assert self.t1.user == clientUser + assert self.s1.user == clientUser + assert self.s1.mech == mech.strip() + assert self.s1.outcome == SASL.OK + else: + # Server + assert self.t2.user == None + assert self.s2.user == None + assert self.s2.outcome != SASL.OK + # Client + assert self.t1.user == clientUser + assert self.s1.user == clientUser + assert self.s1.outcome != SASL.OK + class Test(common.Test): pass @@ -32,6 +92,13 @@ class SaslTest(Test): self.t2 = Transport(Transport.SERVER) self.s2 = SASL(self.t2) + if not SASL.extended(): + return + + _cyrusSetup('sasl_conf') + self.s2.config_name('proton') + self.s2.config_path(os.path.abspath('sasl_conf')) + def pump(self): pump(self.t1, self.t2, 1024) @@ -215,11 +282,11 @@ class SaslTest(Test): self.t2.require_auth(False) self.pump() assert self.s2.outcome == None - self.t2.condition == None - self.t2.authenticated == False + assert self.t2.condition == None + assert self.t2.authenticated == False assert self.s1.outcome == None - self.t1.condition == None - self.t1.authenticated == False + assert self.t1.condition == None + assert self.t1.authenticated == False def testSaslSkippedFail(self): """Verify that the server (with SASL) correctly handles a client without SASL""" @@ -227,6 +294,175 @@ class SaslTest(Test): self.t2.require_auth(True) self.pump() assert self.s2.outcome == None - self.t2.condition != None + assert self.t2.condition != None assert self.s1.outcome == None - self.t1.condition != None + assert self.t1.condition != None + + def testMechNotFound(self): + if "java" in sys.platform: + raise Skipped("Proton-J does not support checking authentication state") + self.c1 = Connection() + self.c1.open() + self.t1.bind(self.c1) + self.s1.allowed_mechs('IMPOSSIBLE') + + self.pump() + + assert self.t2.authenticated == False + assert self.t1.authenticated == False + assert self.s1.outcome != SASL.OK + assert self.s2.outcome != SASL.OK + +class CyrusSASLTest(Test): + def setup(self): + self.t1 = Transport() + self.s1 = SASL(self.t1) + self.t2 = Transport(Transport.SERVER) + self.s2 = SASL(self.t2) + + self.c1 = Connection() + self.c1.user = 'user@proton' + self.c1.password = 'password' + self.c1.hostname = 'localhost' + + if not SASL.extended(): + return + + _cyrusSetup('sasl_conf') + self.s2.config_name('proton') + self.s2.config_path(os.path.abspath('sasl_conf')) + + def testMechANON(self): + self.t1.bind(self.c1) + _testSaslMech(self, 'ANONYMOUS', authUser='anonymous') + + def testMechCRAMMD5(self): + if not SASL.extended(): + raise Skipped('Extended SASL not supported') + + self.t1.bind(self.c1) + _testSaslMech(self, 'CRAM-MD5') + + def testMechDIGESTMD5(self): + if not SASL.extended(): + raise Skipped('Extended SASL not supported') + + self.t1.bind(self.c1) + _testSaslMech(self, 'DIGEST-MD5') + +# SCRAM not supported before Cyrus SASL 2.1.26 +# so not universal and hance need a test for support +# to keep it in tests. +# def testMechSCRAMSHA1(self): +# if not SASL.extended(): +# raise Skipped('Extended SASL not supported') +# +# self.t1.bind(self.c1) +# _testSaslMech(self, 'SCRAM-SHA-1') + +def _sslConnection(domain, transport, connection): + transport.bind(connection) + ssl = SSL(transport, domain, None ) + return connection + +class SSLSASLTest(Test): + def setup(self): + if not common.isSSLPresent(): + raise Skipped("No SSL libraries found.") + + self.server_domain = SSLDomain(SSLDomain.MODE_SERVER) + self.client_domain = SSLDomain(SSLDomain.MODE_CLIENT) + + self.t1 = Transport() + self.s1 = SASL(self.t1) + self.t2 = Transport(Transport.SERVER) + self.s2 = SASL(self.t2) + + self.c1 = Connection() + + if not SASL.extended(): + return + + _cyrusSetup('sasl_conf') + self.s2.config_name('proton') + self.s2.config_path(os.path.abspath('sasl_conf')) + + def testSSLPlainSimple(self): + if "java" in sys.platform: + raise Skipped("Proton-J does not support SSL with SASL") + if not SASL.extended(): + raise Skipped("Simple SASL server does not support PLAIN") + + clientUser = 'user@proton' + mech = 'PLAIN' + + self.c1.user = clientUser + self.c1.password = 'password' + self.c1.hostname = 'localhost' + + ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) + ssl2 = _sslConnection(self.server_domain, self.t2, Connection()) + + _testSaslMech(self, mech, encrypted=True) + + def testSSLPlainSimpleFail(self): + if "java" in sys.platform: + raise Skipped("Proton-J does not support SSL with SASL") + if not SASL.extended(): + raise Skipped("Simple SASL server does not support PLAIN") + + clientUser = 'usr@proton' + mech = 'PLAIN' + + self.c1.user = clientUser + self.c1.password = 'password' + self.c1.hostname = 'localhost' + + ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) + ssl2 = _sslConnection(self.server_domain, self.t2, Connection()) + + _testSaslMech(self, mech, clientUser='usr@proton', encrypted=True, authenticated=False) + + def testSSLExternalSimple(self): + if "java" in sys.platform: + raise Skipped("Proton-J does not support SSL with SASL") + + extUser = 'O=Client,CN=127.0.0.1' + mech = 'EXTERNAL' + + self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"), + _sslCertpath("server-private-key.pem"), + "server-password") + self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) + self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER, + _sslCertpath("ca-certificate.pem") ) + self.client_domain.set_credentials(_sslCertpath("client-certificate.pem"), + _sslCertpath("client-private-key.pem"), + "client-password") + self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) + self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER) + + ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) + ssl2 = _sslConnection(self.server_domain, self.t2, Connection()) + + _testSaslMech(self, mech, clientUser=None, authUser=extUser, encrypted=True) + + def testSSLExternalSimpleFail(self): + if "java" in sys.platform: + raise Skipped("Proton-J does not support SSL with SASL") + + mech = 'EXTERNAL' + + self.server_domain.set_credentials(_sslCertpath("server-certificate.pem"), + _sslCertpath("server-private-key.pem"), + "server-password") + self.server_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) + self.server_domain.set_peer_authentication(SSLDomain.VERIFY_PEER, + _sslCertpath("ca-certificate.pem") ) + self.client_domain.set_trusted_ca_db(_sslCertpath("ca-certificate.pem")) + self.client_domain.set_peer_authentication(SSLDomain.VERIFY_PEER) + + ssl1 = _sslConnection(self.client_domain, self.t1, self.c1) + ssl2 = _sslConnection(self.server_domain, self.t2, Connection()) + + _testSaslMech(self, mech, clientUser=None, authUser=None, encrypted=None, authenticated=False) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org For additional commands, e-mail: commits-help@qpid.apache.org