diff options
Diffstat (limited to 'M4-RCs/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp')
-rw-r--r-- | M4-RCs/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp | 337 |
1 files changed, 0 insertions, 337 deletions
diff --git a/M4-RCs/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp b/M4-RCs/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp deleted file mode 100644 index 370de8a1d1..0000000000 --- a/M4-RCs/qpid/cpp/src/qpid/broker/SaslAuthenticator.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "Connection.h" -#include "qpid/log/Statement.h" -#include "qpid/framing/reply_exceptions.h" -#include <boost/format.hpp> - -#if HAVE_SASL -#include <sasl/sasl.h> -#endif - -using namespace qpid::framing; -using boost::format; -using boost::str; - -namespace qpid { -namespace broker { - - -class NullAuthenticator : public SaslAuthenticator -{ - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - std::string realm; -public: - NullAuthenticator(Connection& connection); - ~NullAuthenticator(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string&) {} -}; - -#if HAVE_SASL - -class CyrusAuthenticator : public SaslAuthenticator -{ - sasl_conn_t *sasl_conn; - Connection& connection; - framing::AMQP_ClientProxy::Connection client; - - void processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len); - -public: - CyrusAuthenticator(Connection& connection); - ~CyrusAuthenticator(); - void init(); - void getMechanisms(framing::Array& mechanisms); - void start(const std::string& mechanism, const std::string& response); - void step(const std::string& response); - void getUid(std::string& uid); - void getError(std::string& error); -}; - -bool SaslAuthenticator::available(void) -{ - return true; -} - -// Initialize the SASL mechanism; throw if it fails. -void SaslAuthenticator::init(const std::string& saslName) -{ - int code = sasl_server_init(NULL, saslName.c_str()); - if (code != SASL_OK) { - // TODO: Figure out who owns the char* returned by - // sasl_errstring, though it probably does not matter much - throw Exception(sasl_errstring(code, NULL, NULL)); - } -} - -void SaslAuthenticator::fini(void) -{ - sasl_done(); -} - -#else - -typedef NullAuthenticator CyrusAuthenticator; - -bool SaslAuthenticator::available(void) -{ - return false; -} - -void SaslAuthenticator::init(const std::string& /*saslName*/) -{ - throw Exception("Requested authentication but SASL unavailable"); -} - -void SaslAuthenticator::fini(void) -{ - return; -} - -#endif - -std::auto_ptr<SaslAuthenticator> SaslAuthenticator::createAuthenticator(Connection& c) -{ - static bool needWarning = true; - if (c.getBroker().getOptions().auth) { - return std::auto_ptr<SaslAuthenticator>(new CyrusAuthenticator(c)); - } else { - QPID_LOG(warning, "SASL: No Authentication Performed"); - needWarning = false; - return std::auto_ptr<SaslAuthenticator>(new NullAuthenticator(c)); - } -} - -NullAuthenticator::NullAuthenticator(Connection& c) : connection(c), client(c.getOutput()), - realm(c.getBroker().getOptions().realm) {} -NullAuthenticator::~NullAuthenticator() {} - -void NullAuthenticator::getMechanisms(Array& mechanisms) -{ - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value("ANONYMOUS"))); -} - -void NullAuthenticator::start(const string& mechanism, const string& response) -{ - if (mechanism == "PLAIN") { // Old behavior - 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); - i = uid.find_last_of(realm); - if (i == string::npos || i != (uid.size() - 1)) { - uid = str(format("%1%@%2%") % uid % realm); - } - connection.setUserId(uid); - } - } else { - connection.setUserId("anonymous"); - } - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); -} - - -#if HAVE_SASL - -CyrusAuthenticator::CyrusAuthenticator(Connection& c) : sasl_conn(0), connection(c), client(c.getOutput()) -{ - init(); -} - -void CyrusAuthenticator::init() -{ - /* Next to the service name, which specifies the - * /etc/sasl2/<service name>.conf file to read, the realm is - * currently the most important argument below. When - * performing authentication the user that is authenticating - * will be looked up in a specific realm. If none is given - * then the realm defaults to the hostname, which can cause - * confusion when the daemon is run on different hosts that - * may be logically sharing a realm (aka a user domain). This - * is especially important for SASL PLAIN authentication, - * which cannot specify a realm for the user that is - * authenticating. - */ - const char *realm = connection.getBroker().getOptions().realm.c_str(); - int code = sasl_server_new(BROKER_SASL_NAME, /* Service name */ - NULL, /* Server FQDN, gethostname() */ - realm, /* Authentication realm */ - NULL, /* Local IP, needed for some mechanism */ - NULL, /* Remote IP, needed for some mechanism */ - NULL, /* Callbacks */ - 0, /* Connection flags */ - &sasl_conn); - - if (SASL_OK != code) { - QPID_LOG(info, "SASL: Connection creation failed: [" << code << "] " << sasl_errdetail(sasl_conn)); - - // TODO: Change this to an exception signaling - // server error, when one is available - throw ConnectionForcedException("Unable to perform authentication"); - } -} - -CyrusAuthenticator::~CyrusAuthenticator() -{ - if (sasl_conn) { - sasl_dispose(&sasl_conn); - sasl_conn = 0; - } -} - -void CyrusAuthenticator::getError(string& error) -{ - error = string(sasl_errdetail(sasl_conn)); -} - -void CyrusAuthenticator::getUid(string& uid) -{ - int code; - const void* ptr; - - code = sasl_getprop(sasl_conn, SASL_USERNAME, &ptr); - if (SASL_OK != code) - return; - - uid = string(const_cast<char*>(static_cast<const char*>(ptr))); -} - -void CyrusAuthenticator::getMechanisms(Array& mechanisms) -{ - const char *separator = " "; - const char *list; - unsigned int list_len; - int count; - - int code = sasl_listmech(sasl_conn, NULL, - "", separator, "", - &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 ConnectionForcedException("Mechanism listing failed"); - } else { - string mechanism; - unsigned int start; - unsigned int end; - - QPID_LOG(info, "SASL: Mechanism list: " << list); - - end = 0; - do { - start = end; - - // Seek to end of next mechanism - while (end < list_len && separator[0] != list[end]) - end++; - - // Record the mechanism - mechanisms.add(boost::shared_ptr<FieldValue>(new Str16Value(string(list, start, end - start)))); - end++; - } while (end < list_len); - } -} - -void CyrusAuthenticator::start(const string& mechanism, const string& response) -{ - const char *challenge; - unsigned int challenge_len; - - QPID_LOG(info, "SASL: Starting authentication with mechanism: " << mechanism); - int code = sasl_server_start(sasl_conn, - mechanism.c_str(), - response.c_str(), response.length(), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); -} - -void CyrusAuthenticator::step(const string& response) -{ - const char *challenge; - unsigned int challenge_len; - - int code = sasl_server_step(sasl_conn, - response.c_str(), response.length(), - &challenge, &challenge_len); - - processAuthenticationStep(code, challenge, challenge_len); -} - -void CyrusAuthenticator::processAuthenticationStep(int code, const char *challenge, unsigned int challenge_len) -{ - if (SASL_OK == code) { - const void *uid; - - 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: " - << const_cast<char*>(static_cast<const char*>(uid))); - - connection.setUserId(const_cast<char*>(static_cast<const char*>(uid))); - - client.tune(framing::CHANNEL_MAX, connection.getFrameMax(), 0, 0); - } 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 - -}} |