summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGordon Sim <gsim@apache.org>2008-04-14 19:19:27 +0000
committerGordon Sim <gsim@apache.org>2008-04-14 19:19:27 +0000
commitbe454984582db8163c7d88e20b07995f2ccdced8 (patch)
treec7195d183779749ffa1481d4a722d3d79a34a8c2
parent0e4526fa8f381e2275d05be03de81802bc0dcabc (diff)
downloadqpid-python-be454984582db8163c7d88e20b07995f2ccdced8.tar.gz
QPID-648: more flexible sasl implementation (patch provided by mfarrellee@redhat.com)
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@647940 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--cpp/src/qpid/broker/Broker.h2
-rw-r--r--cpp/src/qpid/broker/PreviewConnection.cpp3
-rw-r--r--cpp/src/qpid/broker/PreviewConnection.h2
-rw-r--r--cpp/src/qpid/broker/PreviewConnectionHandler.cpp198
-rw-r--r--cpp/src/qpid/broker/PreviewConnectionHandler.h8
-rw-r--r--cpp/src/qpid/sys/AsynchIOAcceptor.cpp18
6 files changed, 161 insertions, 70 deletions
diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h
index 8d39c6005d..ea29348c16 100644
--- a/cpp/src/qpid/broker/Broker.h
+++ b/cpp/src/qpid/broker/Broker.h
@@ -22,8 +22,6 @@
*
*/
-#include "config.h"
-
#include "ConnectionFactory.h"
#include "ConnectionToken.h"
#include "DirectExchange.h"
diff --git a/cpp/src/qpid/broker/PreviewConnection.cpp b/cpp/src/qpid/broker/PreviewConnection.cpp
index 56de374b4d..ad4497b24e 100644
--- a/cpp/src/qpid/broker/PreviewConnection.cpp
+++ b/cpp/src/qpid/broker/PreviewConnection.cpp
@@ -18,9 +18,6 @@
* under the License.
*
*/
-
-#include "config.h"
-
#include "PreviewConnection.h"
#include "SessionState.h"
#include "BrokerAdapter.h"
diff --git a/cpp/src/qpid/broker/PreviewConnection.h b/cpp/src/qpid/broker/PreviewConnection.h
index 1faf4195b5..7a8404bf77 100644
--- a/cpp/src/qpid/broker/PreviewConnection.h
+++ b/cpp/src/qpid/broker/PreviewConnection.h
@@ -21,8 +21,6 @@
#ifndef _PreviewConnection_
#define _PreviewConnection_
-#include "config.h"
-
#include <memory>
#include <sstream>
#include <vector>
diff --git a/cpp/src/qpid/broker/PreviewConnectionHandler.cpp b/cpp/src/qpid/broker/PreviewConnectionHandler.cpp
index 48b8997545..3a19ef416d 100644
--- a/cpp/src/qpid/broker/PreviewConnectionHandler.cpp
+++ b/cpp/src/qpid/broker/PreviewConnectionHandler.cpp
@@ -69,11 +69,43 @@ void PreviewConnectionHandler::handle(framing::AMQFrame& frame)
PreviewConnectionHandler::PreviewConnectionHandler(PreviewConnection& connection, bool isClient) : handler(new Handler(connection)) {
FieldTable properties;
- string mechanisms(PLAIN);
+ string mechanisms;
string locales(en_US);
if (isClient) {
handler->serverMode = false;
}else {
+//
+// TODO: The code below is the proper way to create a mechanisms list,
+// but it cannot be done here because the sasl_conn has not been
+// initialized. Unfortunately, sasl_conn cannot be initialize here
+// because an exception thrown from this constructor will result in
+// the Broker exiting, and dropping core.
+//
+//#if HAVE_SASL
+// const char *list;
+// unsigned int list_len;
+// int count;
+// int code = sasl_listmech(sasl_conn, NULL,
+// "", " ", "",
+// &list, &list_len,
+// &count);
+//
+// if (SASL_OK != code) {
+// QPID_LOG(info, "SASL: Mechanism listing failed: "
+// << sasl_errdetail(sasl_conn));
+//
+// // TODO: Change this to an exception signaling
+// // server error, when one is available
+// throw CommandInvalidException("Mechanism listing failed");
+// } else {
+// // TODO: Figure out the proper way to specify multiple
+// // mechanisms. Right now mechanisms are separated by
+// // spaces.
+// mechanisms = list;
+// }
+//#else
+ mechanisms = PLAIN;
+//#endif
handler->serverMode = true;
handler->client.start(99, 0, properties, mechanisms, locales);
}
@@ -89,7 +121,7 @@ PreviewConnectionHandler::Handler::Handler(PreviewConnection& c) :
PreviewConnectionHandler::Handler::~Handler()
{
-#if HAVE_LIBSASL2
+#if HAVE_SASL
if (NULL != sasl_conn) {
sasl_dispose(&sasl_conn);
sasl_conn = NULL;
@@ -97,71 +129,123 @@ PreviewConnectionHandler::Handler::~Handler()
#endif
}
-void PreviewConnectionHandler::Handler::startOk(const framing::FieldTable& /*clientProperties*/,
- const string& mechanism,
- const string& response, const string& /*locale*/)
+#if HAVE_SASL
+void PreviewConnectionHandler::Handler::processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len)
{
- //TODO: handle SASL mechanisms more cleverly
- if (mechanism == PLAIN) {
- QPID_LOG(info, "SASL Plain: Attempting authentication");
- if (response.size() > 0 && response[0] == (char) 0) {
- string temp = response.substr(1);
- string::size_type i = temp.find((char)0);
- string uid = temp.substr(0, i);
- string pwd = temp.substr(i + 1);
+ if (SASL_OK == code) {
+ const void *uid;
-#if HAVE_SASL
- if (connection.getBroker().getOptions().auth) {
- int code = sasl_server_new(BROKER_SASL_NAME,
- NULL, NULL, NULL, NULL, NULL, 0,
- &sasl_conn);
-
- if (SASL_OK != code) {
- QPID_LOG(info, "SASL Plain: Connection creation failed: "
- << sasl_errdetail(sasl_conn));
-
- // TODO: Change this to an exception signaling
- // server error, when one is available
- throw CommandInvalidException("Unable to perform authentication");
- }
-
- code = sasl_checkpass(sasl_conn,
- uid.c_str(), uid.length(),
- pwd.c_str(), pwd.length());
- if (SASL_OK == code) {
- QPID_LOG(info, "SASL Plain: Authentication accepted for " << uid);
- } else {
- // See man sasl_errors(3) or sasl/sasl.h for possible errors
- QPID_LOG(info, "SASL Plain: Authentication rejected for "
- << uid << ": "
- << sasl_errdetail(sasl_conn));
-
- // TODO: Change this to an exception signaling
- // authentication failure, when one is available
- throw ConnectionForcedException("Authentication failed");
- }
- } else {
+ code = sasl_getprop(sasl_conn,
+ SASL_USERNAME,
+ &uid);
+ if (SASL_OK != code) {
+ QPID_LOG(info, "SASL: Authentication succeeded, username unavailable");
+ // TODO: Change this to an exception signaling
+ // authentication failure, when one is available
+ throw ConnectionForcedException("Authenticated username unavailable");
+ }
+
+ QPID_LOG(info, "SASL: Authentication succeeded for: " << (char *)uid);
+
+ connection.setUserId((char *)uid);
+
+ client.tune(framing::CHANNEL_MAX,
+ connection.getFrameMax(),
+ connection.getHeartbeat());
+ } else if (SASL_CONTINUE == code) {
+ string challenge_str(challenge, challenge_len);
+
+ QPID_LOG(debug, "SASL: sending challenge to client");
+
+ client.secure(challenge_str);
+ } else {
+ QPID_LOG(info, "SASL: Authentication failed: "
+ << sasl_errdetail(sasl_conn));
+
+ // TODO: Change to more specific exceptions, when they are
+ // available
+ switch (code) {
+ case SASL_NOMECH:
+ throw ConnectionForcedException("Unsupported mechanism");
+ break;
+ case SASL_TRYAGAIN:
+ throw ConnectionForcedException("Transient failure, try again");
+ break;
+ default:
+ throw ConnectionForcedException("Authentication failed");
+ break;
+ }
+ }
+}
#endif
- QPID_LOG(warning,
- "SASL Plain Warning: No Authentication Performed for "
- << uid);
+
+void PreviewConnectionHandler::Handler::startOk(const framing::FieldTable& /*clientProperties*/,
#if HAVE_SASL
- }
+ const string& mechanism,
+ const string& response,
+#else
+ const string& /*mechanism*/,
+ const string& /*response*/,
#endif
+ const string& /*locale*/)
+{
+#if HAVE_SASL
+ if (connection.getBroker().getOptions().auth) {
+ int code = sasl_server_new(BROKER_SASL_NAME,
+ NULL, NULL, NULL, NULL, NULL, 0,
+ &sasl_conn);
+
+ if (SASL_OK != code) {
+ QPID_LOG(info, "SASL: Connection creation failed: "
+ << sasl_errdetail(sasl_conn));
- connection.setUserId(uid);
+ // TODO: Change this to an exception signaling
+ // server error, when one is available
+ throw CommandInvalidException("Unable to perform authentication");
}
+
+ const char *challenge;
+ unsigned int challenge_len;
+
+ QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism);
+ code = sasl_server_start(sasl_conn,
+ mechanism.c_str(),
+ response.c_str(), response.length(),
+ &challenge, &challenge_len);
+
+ processAuthenticationStep(code, challenge, challenge_len);
} else {
- // The 0-10 spec states that if the client requests a
- // mechanism not proposed by the server the server MUST
- // close the connection. Assumption here is if we proposed
- // a mechanism we'd have a case for it above.
- throw NotImplementedException("Unsupported authentication mechanism");
- }
- client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), connection.getHeartbeat());
+#endif
+ QPID_LOG(warning, "SASL: No Authentication Performed");
+
+ // TODO: Figure out what should actually be set in this case
+ connection.setUserId("anonymous");
+
+ client.tune(framing::CHANNEL_MAX,
+ connection.getFrameMax(),
+ connection.getHeartbeat());
+#if HAVE_SASL
+ }
+#endif
}
-void PreviewConnectionHandler::Handler::secureOk(const string& /*response*/){}
+void PreviewConnectionHandler::Handler::secureOk(const string&
+#if HAVE_SASL
+ response
+#endif
+ ) {
+#if HAVE_SASL
+ int code;
+ const char *challenge;
+ unsigned int challenge_len;
+
+ code = sasl_server_step(sasl_conn,
+ response.c_str(), response.length(),
+ &challenge, &challenge_len);
+
+ processAuthenticationStep(code, challenge, challenge_len);
+#endif
+}
void PreviewConnectionHandler::Handler::tuneOk(uint16_t /*channelmax*/,
uint32_t framemax, uint16_t heartbeat)
diff --git a/cpp/src/qpid/broker/PreviewConnectionHandler.h b/cpp/src/qpid/broker/PreviewConnectionHandler.h
index 0b729628a5..b71068d81d 100644
--- a/cpp/src/qpid/broker/PreviewConnectionHandler.h
+++ b/cpp/src/qpid/broker/PreviewConnectionHandler.h
@@ -21,6 +21,8 @@
#ifndef _PreviewConnectionAdapter_
#define _PreviewConnectionAdapter_
+#include "config.h"
+
#include <memory>
#include "qpid/framing/amqp_types.h"
#include "qpid/framing/AMQFrame.h"
@@ -85,6 +87,12 @@ class PreviewConnectionHandler : public framing::FrameHandler
void openOk(const std::string& knownHosts);
void redirect(const std::string& host, const std::string& knownHosts);
+ private:
+#if HAVE_SASL
+ void processAuthenticationStep(int code,
+ const char *challenge,
+ unsigned int challenge_len);
+#endif
};
std::auto_ptr<Handler> handler;
public:
diff --git a/cpp/src/qpid/sys/AsynchIOAcceptor.cpp b/cpp/src/qpid/sys/AsynchIOAcceptor.cpp
index 153557c5e5..5c784912b3 100644
--- a/cpp/src/qpid/sys/AsynchIOAcceptor.cpp
+++ b/cpp/src/qpid/sys/AsynchIOAcceptor.cpp
@@ -246,13 +246,19 @@ void AsynchIOHandler::readbuff(AsynchIO& , AsynchIO::BufferBase* buff) {
if (protocolInit.decode(in)) {
decoded = in.getPosition();
QPID_LOG(debug, "RECV [" << identifier << "] INIT(" << protocolInit << ")");
- codec = factory->create(protocolInit.getVersion(), *this, identifier);
- if (!codec) {
- //TODO: may still want to revise this...
- //send valid version header & close connection.
- write(framing::ProtocolInitiation(framing::highestProtocolVersion));
+ try {
+ codec = factory->create(protocolInit.getVersion(), *this, identifier);
+ if (!codec) {
+ //TODO: may still want to revise this...
+ //send valid version header & close connection.
+ write(framing::ProtocolInitiation(framing::highestProtocolVersion));
+ readError = true;
+ aio->queueWriteClose();
+ }
+ } catch (const std::exception& e) {
+ QPID_LOG(error, e.what());
readError = true;
- aio->queueWriteClose();
+ aio->queueWriteClose();
}
}
}