diff options
author | Gordon Sim <gsim@apache.org> | 2008-04-14 19:19:27 +0000 |
---|---|---|
committer | Gordon Sim <gsim@apache.org> | 2008-04-14 19:19:27 +0000 |
commit | be454984582db8163c7d88e20b07995f2ccdced8 (patch) | |
tree | c7195d183779749ffa1481d4a722d3d79a34a8c2 | |
parent | 0e4526fa8f381e2275d05be03de81802bc0dcabc (diff) | |
download | qpid-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.h | 2 | ||||
-rw-r--r-- | cpp/src/qpid/broker/PreviewConnection.cpp | 3 | ||||
-rw-r--r-- | cpp/src/qpid/broker/PreviewConnection.h | 2 | ||||
-rw-r--r-- | cpp/src/qpid/broker/PreviewConnectionHandler.cpp | 198 | ||||
-rw-r--r-- | cpp/src/qpid/broker/PreviewConnectionHandler.h | 8 | ||||
-rw-r--r-- | cpp/src/qpid/sys/AsynchIOAcceptor.cpp | 18 |
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(); } } } |