Author: gsim
Date: Mon Apr 14 12:19:27 2008
New Revision: 647940

URL: http://svn.apache.org/viewvc?rev=647940&view=rev
Log:
QPID-648: more flexible sasl implementation (patch provided by [EMAIL 
PROTECTED])


Modified:
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h?rev=647940&r1=647939&r2=647940&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.h Mon Apr 14 12:19:27 
2008
@@ -22,8 +22,6 @@
  *
  */
 
-#include "config.h"
-
 #include "ConnectionFactory.h"
 #include "ConnectionToken.h"
 #include "DirectExchange.h"

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.cpp?rev=647940&r1=647939&r2=647940&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.cpp 
(original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.cpp Mon Apr 
14 12:19:27 2008
@@ -18,9 +18,6 @@
  * under the License.
  *
  */
-
-#include "config.h"
-
 #include "PreviewConnection.h"
 #include "SessionState.h"
 #include "BrokerAdapter.h"

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.h?rev=647940&r1=647939&r2=647940&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnection.h Mon Apr 
14 12:19:27 2008
@@ -21,8 +21,6 @@
 #ifndef _PreviewConnection_
 #define _PreviewConnection_
 
-#include "config.h"
-
 #include <memory>
 #include <sstream>
 #include <vector>

Modified: 
incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp?rev=647940&r1=647939&r2=647940&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp 
(original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.cpp 
Mon Apr 14 12:19:27 2008
@@ -69,11 +69,43 @@
 
 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() 
 {
-#if HAVE_LIBSASL2
+#if HAVE_SASL
     if (NULL != sasl_conn) {
         sasl_dispose(&sasl_conn);
         sasl_conn = NULL;
@@ -97,71 +129,123 @@
 #endif
 }
 
-void PreviewConnectionHandler::Handler::startOk(const framing::FieldTable& 
/*clientProperties*/,
-    const string& mechanism, 
-    const string& response, const string& /*locale*/)
-{
-    //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 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 {
-#endif
-                QPID_LOG(warning,
-                         "SASL Plain Warning: No Authentication Performed for "
-                         << uid);
 #if HAVE_SASL
-            }
+void PreviewConnectionHandler::Handler::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: " << (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
 
-            connection.setUserId(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));
+
+                // 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)

Modified: 
incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h?rev=647940&r1=647939&r2=647940&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h 
(original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/PreviewConnectionHandler.h 
Mon Apr 14 12:19:27 2008
@@ -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 @@
         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:

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp?rev=647940&r1=647939&r2=647940&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/AsynchIOAcceptor.cpp Mon Apr 14 
12:19:27 2008
@@ -246,13 +246,19 @@
         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();
             }
         }
     }


Reply via email to