diff options
| author | Ted Ross <tross@apache.org> | 2009-01-20 21:26:28 +0000 |
|---|---|---|
| committer | Ted Ross <tross@apache.org> | 2009-01-20 21:26:28 +0000 |
| commit | 861692abf515cf136e86e70446d005e7849a0f87 (patch) | |
| tree | 10025e3499876dbdae8697f2dda4c68b4ec55933 /ruby/lib/qpid | |
| parent | 15488eba1c867bac8b6db1f7ad870b277c4fa748 (diff) | |
| download | qpid-python-861692abf515cf136e86e70446d005e7849a0f87.tar.gz | |
QPID-1602 SASL Authentication, Authorization, and Security Layer for Ruby Client.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@736111 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'ruby/lib/qpid')
| -rw-r--r-- | ruby/lib/qpid/delegates.rb | 36 | ||||
| -rw-r--r-- | ruby/lib/qpid/framer.rb | 35 | ||||
| -rw-r--r-- | ruby/lib/qpid/qmf.rb | 43 |
3 files changed, 89 insertions, 25 deletions
diff --git a/ruby/lib/qpid/delegates.rb b/ruby/lib/qpid/delegates.rb index 21513fc677..9707cdbc76 100644 --- a/ruby/lib/qpid/delegates.rb +++ b/ruby/lib/qpid/delegates.rb @@ -18,6 +18,7 @@ # require 'rbconfig' +require 'sasl' module Qpid @@ -173,9 +174,17 @@ module Qpid def initialize(connection, args) super(connection) - @username = args[:username] || "guest" - @password = args[:password] || "guest" - @mechanism= args[:mechanism] || "PLAIN" + result = Sasl::client_init + + @mechanism= args[:mechanism] + @username = args[:username] + @password = args[:password] + @service = args[:service] || "qpidd" + @min_ssf = args[:min_ssf] || 0 + @max_ssf = args[:max_ssf] || 65535 + + @saslConn = Sasl.client_new(@mechanism, @service, args[:host], + @username, @password, @min_ssf, @max_ssf) end def start @@ -184,18 +193,31 @@ module Qpid end def connection_start(ch, start) - r = "\0%s\0%s" % [@username, @password] + mech_list = "" + start.mechanisms.each do |m| + mech_list += m + " " + end + resp = Sasl.client_start(@saslConn, mech_list) ch.connection_start_ok(:client_properties => PROPERTIES, - :mechanism => @mechanism, - :response => r) + :mechanism => resp[2], + :response => resp[1]) + end + + def connection_secure(ch, secure) + resp = Sasl.client_step(@saslConn, secure.challenge) + ch.connection_secure_ok(:response => resp[1]) end def connection_tune(ch, tune) - ch.connection_tune_ok() + ch.connection_tune_ok(:channel_max => tune.channel_max, + :max_frame_size => tune.max_frame_size, + :heartbeat => 0) ch.connection_open() + @connection.security_layer_tx = @saslConn end def connection_open_ok(ch, open_ok) + @connection.security_layer_rx = @saslConn @connection.opened = true @connection.signal end diff --git a/ruby/lib/qpid/framer.rb b/ruby/lib/qpid/framer.rb index 2a565a69a8..abac221f00 100644 --- a/ruby/lib/qpid/framer.rb +++ b/ruby/lib/qpid/framer.rb @@ -19,6 +19,7 @@ require 'monitor' require 'logger' +require 'sasl' module Qpid @@ -109,21 +110,31 @@ module Qpid def initialize(sock) @sock = sock @sock.extend(MonitorMixin) - @buf = "" + @tx_buf = "" + @rx_buf = "" + @security_layer_tx = nil + @security_layer_rx = nil + @maxbufsize = 65535 end attr_reader :sock + attr_accessor :security_layer_tx, :security_layer_rx def aborted? ; false ; end def write(buf) - @buf += buf + @tx_buf += buf end def flush @sock.synchronize do - _write(@buf) - @buf = "" + if @security_layer_tx + cipher_buf = Sasl.encode(@security_layer_tx, @tx_buf) + _write(cipher_buf) + else + _write(@tx_buf) + end + @tx_buf = "" frm.debug("FLUSHED") if frm end end @@ -139,12 +150,14 @@ module Qpid end def read(n) - data = "" - while data.size < n + while @rx_buf.size < n begin - s = @sock.read(n - data.size) + s = @sock.recv(@maxbufsize) + if @security_layer_rx + s = Sasl.decode(@security_layer_rx, s) + end rescue IOError => e - raise e if data != "" + raise e if @rx_buf != "" @sock.close unless @sock.closed? raise Closed end @@ -153,9 +166,11 @@ module Qpid @sock.close unless @sock.closed? raise Closed end - data += s - raw.debug("RECV #{n}/#{data.size} #{s.inspect}") if raw + @rx_buf += s + raw.debug("RECV #{n}/#{@rx_buf.size} #{s.inspect}") if raw end + data = @rx_buf[0, n] + @rx_buf = @rx_buf[n, @rx_buf.size - n] return data end diff --git a/ruby/lib/qpid/qmf.rb b/ruby/lib/qpid/qmf.rb index 0309b65a6c..ee165305c3 100644 --- a/ruby/lib/qpid/qmf.rb +++ b/ruby/lib/qpid/qmf.rb @@ -65,16 +65,15 @@ module Qpid::Qmf class BrokerURL - attr_reader :host, :port, :auth_name, :auth_pass, :auth_mech + attr_reader :host, :port, :auth_name, :auth_pass def initialize(text) uri = URI.parse(text) @host = uri.host @port = uri.port ? uri.port : 5672 - @auth_name = uri.user ? uri.user : "guest" - @auth_pass = uri.password ? uri.password: "guest" - @auth_mech = "PLAIN" + @auth_name = uri.user + @auth_pass = uri.password return uri end @@ -178,9 +177,32 @@ module Qpid::Qmf end # Connect to a Qpid broker. Returns an object of type Broker - def add_broker(target="amqp://localhost") + # + # To supply a username for authentication, use the URL syntax: + # + # amqp://username@hostname:port + # + # If the broker needs a password for the client, an interactive prompt will be + # provided to the user. + # + # To supply a username and a password, use + # + # amqp://username:password@hostname:port + # + # The following keyword arguments may be used to control authentication: + # + # :mechanism - SASL mechanism (i.e. "PLAIN", "GSSAPI", "ANONYMOUS", etc. + # - defaults to unspecified (the system chooses for you) + # :service - SASL service name (i.e. the kerberos principal of the broker) + # - defaults to "qpidd" + # :min_ssf - Minimum Security Strength Factor for SASL security layers + # - defaults to 0 + # :max_ssf - Maximum Security Strength Factor for SASL security layers + # - defaults to 65535 + # + def add_broker(target = "amqp://localhost", kwargs = {}) url = BrokerURL.new(target) - broker = Broker.new(self, url.host, url.port, url.auth_mech, url.auth_name, url.auth_pass) + broker = Broker.new(self, url.host, url.port, url.auth_name, url.auth_pass, kwargs) unless broker.connected? || @manage_connections raise broker.error end @@ -1201,7 +1223,7 @@ module Qpid::Qmf attr_accessor :broker_id, :sync_result - def initialize(session, host, port, auth_mech, auth_name, auth_pass) + def initialize(session, host, port, auth_name, auth_pass, kwargs) super() # For debugging.. @@ -1212,6 +1234,8 @@ module Qpid::Qmf @port = port @auth_name = auth_name @auth_pass = auth_pass + @auth_mechanism = kwargs[:mechanism] + @auth_service = kwargs[:service] @broker_bank = 1 @agents = {} @agents["1.0"] = Agent.new(self, 0, "BrokerAgent") @@ -1368,8 +1392,11 @@ module Qpid::Qmf # FIXME: Need sth for Qpid::Util::connect @conn = Qpid::Connection.new(TCPSocket.new(@host, @port), + :mechanism => @auth_mechanism, :username => @auth_name, - :password => @auth_pass) + :password => @auth_pass, + :host => @host, + :service => @auth_service) @conn.start @reply_name = "reply-%s" % amqp_session_id @amqp_session = @conn.session(@amqp_session_id) |
