summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/broker/PreviewConnectionHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/qpid/broker/PreviewConnectionHandler.cpp')
-rw-r--r--cpp/src/qpid/broker/PreviewConnectionHandler.cpp198
1 files changed, 141 insertions, 57 deletions
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)