Author: rhs
Date: Thu Oct 4 11:08:33 2012
New Revision: 1393985
URL: http://svn.apache.org/viewvc?rev=1393985&view=rev
Log:
applied patch from PROTON-56 and fixed challenge/response to work properly
Modified:
qpid/proton/trunk/proton-c/bindings/python/proton.py
qpid/proton/trunk/proton-c/bindings/python/python.i
qpid/proton/trunk/proton-c/src/sasl/sasl.c
qpid/proton/trunk/tests/proton_tests/sasl.py
Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1393985&r1=1393984&r2=1393985&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
+++ qpid/proton/trunk/proton-c/bindings/python/proton.py Thu Oct 4 11:08:33
2012
@@ -1526,6 +1526,9 @@ class Transport(object):
else:
return self._check(n)
+class SASLException(TransportException):
+ pass
+
class SASL(object):
OK = PN_SASL_OK
@@ -1534,6 +1537,13 @@ class SASL(object):
def __init__(self, transport):
self._sasl = pn_sasl(transport._trans)
+ def _check(self, err):
+ if err < 0:
+ exc = EXCEPTIONS.get(err, SASLException)
+ raise exc("[%s]" % (err))
+ else:
+ return err
+
def mechanisms(self, mechs):
pn_sasl_mechanisms(self._sasl, mechs)
@@ -1543,6 +1553,25 @@ class SASL(object):
def server(self):
pn_sasl_server(self._sasl)
+ def plain(self, user, password):
+ pn_sasl_plain(self._sasl, user, password)
+
+ def send(self, data):
+ self._check(pn_sasl_send(self._sasl, data, len(data)))
+
+ def recv(self):
+ sz = 16
+ while True:
+ n, data = pn_sasl_recv(self._sasl, sz)
+ if n == PN_OVERFLOW:
+ sz *= 2
+ continue
+ elif n == PN_EOS:
+ return None
+ else:
+ self._check(n)
+ return data
+
@property
def outcome(self):
outcome = pn_sasl_outcome(self._sasl)
Modified: qpid/proton/trunk/proton-c/bindings/python/python.i
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/python.i?rev=1393985&r1=1393984&r2=1393985&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/python.i (original)
+++ qpid/proton/trunk/proton-c/bindings/python/python.i Thu Oct 4 11:08:33 2012
@@ -375,5 +375,19 @@ ssize_t pn_data_decode(pn_data_t *data,
%}
%ignore pn_data_encode;
+%rename(pn_sasl_recv) wrap_pn_sasl_recv;
+%inline %{
+ int wrap_pn_sasl_recv(pn_sasl_t *sasl, char *OUTPUT, size_t *OUTPUT_SIZE) {
+ ssize_t sz = pn_sasl_recv(sasl, OUTPUT, *OUTPUT_SIZE);
+ if (sz >= 0) {
+ *OUTPUT_SIZE = sz;
+ } else {
+ *OUTPUT_SIZE = 0;
+ }
+ return sz;
+ }
+%}
+%ignore pn_sasl_recv;
+
%include "proton/cproton.i"
Modified: qpid/proton/trunk/proton-c/src/sasl/sasl.c
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/sasl/sasl.c?rev=1393985&r1=1393984&r2=1393985&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/src/sasl/sasl.c (original)
+++ qpid/proton/trunk/proton-c/src/sasl/sasl.c Thu Oct 4 11:08:33 2012
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <proton/buffer.h>
#include <proton/framing.h>
#include <proton/engine.h> // XXX: just needed for PN_EOS
#include <proton/sasl.h>
@@ -38,8 +39,8 @@ struct pn_sasl_t {
bool configured;
char *mechanisms;
char *remote_mechanisms;
- pn_bytes_t send_data;
- pn_bytes_t recv_data;
+ pn_buffer_t *send_data;
+ pn_buffer_t *recv_data;
pn_sasl_outcome_t outcome;
bool sent_init;
bool rcvd_init;
@@ -70,8 +71,8 @@ pn_sasl_t *pn_sasl(pn_transport_t *trans
sasl->configured = false;
sasl->mechanisms = NULL;
sasl->remote_mechanisms = NULL;
- sasl->send_data = (pn_bytes_t) {0, NULL};
- sasl->recv_data = (pn_bytes_t) {0, NULL};
+ sasl->send_data = pn_buffer(16);
+ sasl->recv_data = pn_buffer(16);
sasl->outcome = PN_SASL_NONE;
sasl->sent_init = false;
sasl->rcvd_init = false;
@@ -117,11 +118,12 @@ const char *pn_sasl_remote_mechanisms(pn
ssize_t pn_sasl_send(pn_sasl_t *sasl, const char *bytes, size_t size)
{
if (sasl) {
- if (sasl->send_data.start) {
+ if (pn_buffer_size(sasl->send_data)) {
// XXX: need better error
return PN_STATE_ERR;
}
- sasl->send_data = pn_bytes_dup(size, bytes);
+ int err = pn_buffer_append(sasl->send_data, bytes, size);
+ if (err) return err;
return size;
} else {
return PN_ARG_ERR;
@@ -130,8 +132,8 @@ ssize_t pn_sasl_send(pn_sasl_t *sasl, co
size_t pn_sasl_pending(pn_sasl_t *sasl)
{
- if (sasl && sasl->recv_data.start) {
- return sasl->recv_data.size;
+ if (sasl && pn_buffer_size(sasl->recv_data)) {
+ return pn_buffer_size(sasl->recv_data);
} else {
return 0;
}
@@ -141,12 +143,12 @@ ssize_t pn_sasl_recv(pn_sasl_t *sasl, ch
{
if (!sasl) return PN_ARG_ERR;
- if (sasl->recv_data.start) {
- if (sasl->recv_data.size > size) return PN_OVERFLOW;
- memmove(bytes, sasl->recv_data.start, sasl->recv_data.size);
- free(sasl->recv_data.start);
- sasl->recv_data = pn_bytes(0, NULL);
- return sasl->recv_data.size;
+ size_t bsize = pn_buffer_size(sasl->recv_data);
+ if (bsize) {
+ if (bsize > size) return PN_OVERFLOW;
+ pn_buffer_get(sasl->recv_data, 0, bsize, bytes);
+ pn_buffer_clear(sasl->recv_data);
+ return bsize;
} else {
return PN_EOS;
}
@@ -211,8 +213,8 @@ void pn_sasl_free(pn_sasl_t *sasl)
if (sasl) {
free(sasl->mechanisms);
free(sasl->remote_mechanisms);
- free(sasl->send_data.start);
- free(sasl->recv_data.start);
+ pn_buffer_free(sasl->send_data);
+ pn_buffer_free(sasl->recv_data);
pn_dispatcher_free(sasl->disp);
free(sasl);
}
@@ -220,12 +222,10 @@ void pn_sasl_free(pn_sasl_t *sasl)
void pn_client_init(pn_sasl_t *sasl)
{
+ pn_bytes_t bytes = pn_buffer_bytes(sasl->send_data);
pn_post_frame(sasl->disp, 0, "DL[sz]", SASL_INIT, sasl->mechanisms,
- sasl->send_data.size, sasl->send_data.start);
- if (sasl->send_data.start) {
- free(sasl->send_data.start);
- sasl->send_data = pn_bytes(0, NULL);
- }
+ bytes.size, bytes.start);
+ pn_buffer_clear(sasl->send_data);
}
void pn_server_init(pn_sasl_t *sasl)
@@ -277,6 +277,13 @@ void pn_sasl_process(pn_sasl_t *sasl)
sasl->sent_init = true;
}
+ if (pn_buffer_size(sasl->send_data)) {
+ pn_bytes_t bytes = pn_buffer_bytes(sasl->send_data);
+ pn_post_frame(sasl->disp, 0, "DL[z]", sasl->client ? SASL_RESPONSE :
SASL_CHALLENGE,
+ bytes.size, bytes.start);
+ pn_buffer_clear(sasl->send_data);
+ }
+
if (!sasl->client && sasl->outcome != PN_SASL_NONE && !sasl->sent_done) {
pn_server_done(sasl);
sasl->sent_done = true;
@@ -339,7 +346,7 @@ int pn_do_init(pn_dispatcher_t *disp)
int err = pn_scan_args(disp, "D.[sz]", &mech, &recv);
if (err) return err;
sasl->remote_mechanisms = pn_strndup(mech.start, mech.size);
- sasl->recv_data = pn_bytes_dup(recv.size, recv.start);
+ pn_buffer_append(sasl->recv_data, recv.start, recv.size);
sasl->rcvd_init = true;
return 0;
}
@@ -351,14 +358,24 @@ int pn_do_mechanisms(pn_dispatcher_t *di
return 0;
}
+int pn_do_recv(pn_dispatcher_t *disp)
+{
+ pn_sasl_t *sasl = disp->context;
+ pn_bytes_t recv;
+ int err = pn_scan_args(disp, "D.[z]", &recv);
+ if (err) return err;
+ pn_buffer_append(sasl->recv_data, recv.start, recv.size);
+ return 0;
+}
+
int pn_do_challenge(pn_dispatcher_t *disp)
{
- return PN_ERR;
+ return pn_do_recv(disp);
}
-int pn_do_response(pn_dispatcher_t *resp)
+int pn_do_response(pn_dispatcher_t *disp)
{
- return PN_ERR;
+ return pn_do_recv(disp);
}
int pn_do_outcome(pn_dispatcher_t *disp)
Modified: qpid/proton/trunk/tests/proton_tests/sasl.py
URL:
http://svn.apache.org/viewvc/qpid/proton/trunk/tests/proton_tests/sasl.py?rev=1393985&r1=1393984&r2=1393985&view=diff
==============================================================================
--- qpid/proton/trunk/tests/proton_tests/sasl.py (original)
+++ qpid/proton/trunk/tests/proton_tests/sasl.py Thu Oct 4 11:08:33 2012
@@ -25,29 +25,62 @@ class Test(common.Test):
class SaslTest(Test):
- def testPipelined(self):
- cli = Transport()
- cli_auth = SASL(cli)
- cli_auth.mechanisms("ANONYMOUS")
- cli_auth.client()
-
- assert cli_auth.outcome is None
-
- srv = Transport()
- srv_auth = SASL(srv)
- srv_auth.mechanisms("ANONYMOUS")
- srv_auth.server()
- srv_auth.done(SASL.OK)
+ def setup(self):
+ self.t1 = Transport()
+ self.s1 = SASL(self.t1)
+ self.t2 = Transport()
+ self.s2 = SASL(self.t2)
+
+ def pump(self):
+ while True:
+ out1 = self.t1.output(1024)
+ out2 = self.t2.output(1024)
+ if out1: self.t2.input(out1)
+ if out2: self.t1.input(out2)
+ if not out1 and not out2: break
- cli_out = cli.output(1024)
- srv_out = srv.output(1024)
-
- n = srv.input(cli_out)
- assert n == len(cli_out), (n, cli_out)
-
- assert cli_auth.outcome is None
+ def testPipelined(self):
+ self.s1.mechanisms("ANONYMOUS")
+ self.s1.client()
- n = cli.input(srv_out)
- assert n == len(srv_out), n
+ assert self.s1.outcome is None
- assert cli_auth.outcome == SASL.OK
+ self.s2.mechanisms("ANONYMOUS")
+ self.s2.server()
+ self.s2.done(SASL.OK)
+
+ out1 = self.t1.output(1024)
+ out2 = self.t2.output(1024)
+
+ n = self.t2.input(out1)
+ assert n == len(out1), (n, out1)
+
+ assert self.s1.outcome is None
+
+ n = self.t1.input(out2)
+ assert n == len(out2), (n, out2)
+
+ assert self.s2.outcome == SASL.OK
+
+ def testChallengeResponse(self):
+ self.s1.mechanisms("FAKE_MECH")
+ self.s1.client()
+ self.s2.mechanisms("FAKE_MECH")
+ self.s2.server()
+ self.pump()
+ challenge = "Who goes there!"
+ self.s2.send(challenge)
+ self.pump()
+ ch = self.s1.recv()
+ assert ch == challenge, ch
+
+ response = "It is I, Secundus!"
+ self.s1.send(response)
+ self.pump()
+ re = self.s2.recv()
+ assert re == response, re
+
+ def testInitialResponse(self):
+ self.s1.plain("secundus", "trustno1")
+ self.pump()
+ assert self.s2.recv() == "\x00secundus\x00trustno1"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]