summaryrefslogtreecommitdiff
path: root/python/qpid/delegates.py
diff options
context:
space:
mode:
authorTed Ross <tross@apache.org>2009-11-11 17:33:33 +0000
committerTed Ross <tross@apache.org>2009-11-11 17:33:33 +0000
commitea3ed931fde51d95416c8f25520908f170ef716b (patch)
tree1736b3e06ef3391b243b905b883792a40b3eba2d /python/qpid/delegates.py
parentfe2b5f5849574d7281c16b6ba066ced2d25184e2 (diff)
downloadqpid-python-ea3ed931fde51d95416c8f25520908f170ef716b.tar.gz
Added full SASL authentication and security layer for the Python client.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@834975 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'python/qpid/delegates.py')
-rw-r--r--python/qpid/delegates.py78
1 files changed, 70 insertions, 8 deletions
diff --git a/python/qpid/delegates.py b/python/qpid/delegates.py
index 14111a88df..8ebaff4ba3 100644
--- a/python/qpid/delegates.py
+++ b/python/qpid/delegates.py
@@ -20,11 +20,20 @@
import os, connection, session
from util import notify
from datatypes import RangedSet
-from exceptions import VersionError
+from exceptions import VersionError, Closed
from logging import getLogger
from ops import Control
import sys
+_have_sasl = None
+try:
+ import qpidsasl
+ _have_sasl = True
+except:
+ pass
+finally:
+ pass
+
log = getLogger("qpid.io.ctl")
class Delegate:
@@ -152,13 +161,36 @@ class Client(Delegate):
"qpid.client_pid": os.getpid(),
"qpid.client_ppid": ppid}
- def __init__(self, connection, username="guest", password="guest",
- mechanism="PLAIN", heartbeat=None):
+ def __init__(self, connection, username=None, password=None,
+ mechanism=None, heartbeat=None, **kwargs):
Delegate.__init__(self, connection)
- self.username = username
- self.password = password
- self.mechanism = mechanism
+
+ ##
+ ## self.acceptableMechanisms is the list of SASL mechanisms that the client is willing to
+ ## use. If it's None, then any mechanism is acceptable.
+ ##
+ self.acceptableMechanisms = None
+ if mechanism:
+ self.acceptableMechanisms = mechanism.split(" ")
self.heartbeat = heartbeat
+ self.username = username
+ self.password = password
+
+ if _have_sasl:
+ self.sasl = qpidsasl.Client()
+ if username and len(username) > 0:
+ self.sasl.setAttr("username", str(username))
+ if password and len(password) > 0:
+ self.sasl.setAttr("password", str(password))
+ if "service" in kwargs:
+ self.sasl.setAttr("service", str(kwargs["service"]))
+ if "host" in kwargs:
+ self.sasl.setAttr("host", str(kwargs["host"]))
+ if "min_ssf" in kwargs:
+ self.sasl.setAttr("minssf", kwargs["min_ssf"])
+ if "max_ssf" in kwargs:
+ self.sasl.setAttr("maxssf", kwargs["max_ssf"])
+ self.sasl.init()
def start(self):
# XXX
@@ -171,14 +203,44 @@ class Client(Delegate):
(cli_major, cli_minor, major, minor))
def connection_start(self, ch, start):
- r = "\0%s\0%s" % (self.username, self.password)
- ch.connection_start_ok(client_properties=Client.PROPERTIES, mechanism=self.mechanism, response=r)
+ mech_list = ""
+ for mech in start.mechanisms:
+ if (not self.acceptableMechanisms) or mech in self.acceptableMechanisms:
+ mech_list += str(mech) + " "
+ mech = None
+ initial = None
+ if _have_sasl:
+ status, mech, initial = self.sasl.start(mech_list)
+ if status == False:
+ raise Closed("SASL error: %s" % self.sasl.getError())
+ else:
+ if self.username and self.password and ("PLAIN" in mech_list):
+ mech = "PLAIN"
+ initial = "\0%s\0%s" % (self.username, self.password)
+ else:
+ mech = "ANONYMOUS"
+ if not mech in mech_list:
+ raise Closed("No acceptable SASL authentication mechanism available")
+ ch.connection_start_ok(client_properties=Client.PROPERTIES, mechanism=mech, response=initial)
+
+ def connection_secure(self, ch, secure):
+ resp = None
+ if _have_sasl:
+ status, resp = self.sasl.step(secure.challenge)
+ if status == False:
+ raise Closed("SASL error: %s" % self.sasl.getError())
+ ch.connection_secure_ok(response=resp)
def connection_tune(self, ch, tune):
ch.connection_tune_ok(heartbeat=self.heartbeat)
ch.connection_open()
+ if _have_sasl:
+ self.connection.user_id = self.sasl.getUserId()
+ self.connection.security_layer_tx = self.sasl
def connection_open_ok(self, ch, open_ok):
+ if _have_sasl:
+ self.connection.security_layer_rx = self.sasl
self.connection.opened = True
notify(self.connection.condition)