Author: gsim
Date: Mon Apr 14 02:54:16 2008
New Revision: 647716

URL: http://svn.apache.org/viewvc?rev=647716&view=rev
Log:
QPID-648: Initial support for sasl authentication for c++ broker. From patch 
submitted by [EMAIL PROTECTED]

Authentication is optional at compile time (based on user selection or 
availability of cyrus sasl libs) and at 
runtime (through broker config option). Note: At present the runtime default is 
to not authenticate; this is a
temporary measure to give some time for any automation scripts etc to be 
updated and will revert shortly to be
on by default.


Modified:
    incubator/qpid/trunk/qpid/cpp/configure.ac
    incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
    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/tests/BrokerFixture.h
    incubator/qpid/trunk/qpid/cpp/src/tests/run_federation_tests
    incubator/qpid/trunk/qpid/cpp/src/tests/start_broker

Modified: incubator/qpid/trunk/qpid/cpp/configure.ac
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/configure.ac?rev=647716&r1=647715&r2=647716&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/configure.ac (original)
+++ incubator/qpid/trunk/qpid/cpp/configure.ac Mon Apr 14 02:54:16 2008
@@ -164,7 +164,38 @@
 if test x$with_CPG = xyes; then
   CPPFLAGS+=" -DCPG"
 fi
-       
+
+
+# Setup --with-sasl/--without-sasl as arguments to configure
+AC_ARG_WITH([sasl],
+  [AS_HELP_STRING([--with-sasl], [Build with SASL authentication support])],
+  [WANT_SASL="$withval"],
+  [WANT_SASL=check])
+
+# Make sure --with-sasl/--without-sasl were only give yes|no|check
+AS_IF([test "x$WANT_SASL" != xyes -a \
+            "x$WANT_SASL" != xno -a \
+            "x$WANT_SASL" != xcheck],
+  [AC_MSG_ERROR([Bad value for --with-sasl: $withval])])
+
+# If we weren't explicitly asked /not/ to test, i.e. not given --without-sasl
+AS_IF([test "x$WANT_SASL" != xno],
+  # Perform tests for headers and libraries. Remember, AC_CHECK_LIB
+  # will give you some useful default behavior, e.g. setup LDFLAGS, if
+  # you do not give it a second argument, so try not to
+  [AC_CHECK_HEADER([sasl/sasl.h], , [HAVE_SASL_H=no])
+   AC_CHECK_LIB([sasl2], [sasl_checkpass], , [HAVE_SASL_LIB=no])
+   # If any of the tests failed
+   AS_IF([test "x$HAVE_SASL_H" = xno -o \
+               "x$HAVE_SASL_LIB" = xno],
+     # And we were given --with, then fail
+     [AS_IF([test "x$WANT_SASL" = xyes],
+       [AC_MSG_ERROR([sasl requested but not available])])],
+     # Otherwise, no tests failed, setup AC_SUBST/AC_DEFINE/AM_CONDITIONALs
+     [AC_DEFINE([BROKER_SASL_NAME], ["qpidd"],
+                [The SASL app name for the qpid Broker])
+      AC_DEFINE([HAVE_SASL], [1], [Enable if libsasl is present])])])
+
 # Files to generate    
 AC_CONFIG_FILES([
   qpidc.spec

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp?rev=647716&r1=647715&r2=647716&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/broker/Broker.cpp Mon Apr 14 
02:54:16 2008
@@ -48,6 +48,10 @@
 #include <iostream>
 #include <memory>
 
+#if HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 using qpid::sys::Acceptor;
 using qpid::framing::FrameHandler;
 using qpid::framing::ChannelId;
@@ -71,6 +75,15 @@
     stagingThreshold(5000000),
     enableMgmt(1),
     mgmtPubInterval(10),
+#if HAVE_SASL
+    //Authentication disabled by default for now to allow any
+    //scripts etc that might fail authentication to be updated.
+    //Note that this is a temporary measure (GS 14-APR-2008).
+    auth(false),
+    //auth(true),
+#else
+    auth(false),
+#endif
     ack(0)
 {
     int c = sys::SystemInfo::concurrency();
@@ -94,6 +107,8 @@
          "Enable Management")
         ("mgmt-pub-interval", optValue(mgmtPubInterval, "SECONDS"),
          "Management Publish Interval")
+        ("auth", optValue(auth, "yes|no"),
+         "Enable authentication, if disabled all incoming connections will be 
trusted")
         ("ack", optValue(ack, "N"),
          "Send session.ack/solicit-ack at least every N frames. 0 disables 
voluntary ack/solitict-ack");
 }
@@ -184,6 +199,23 @@
     else
         QPID_LOG(info, "Management not enabled");
 
+    /**
+     * SASL setup, can fail and terminate startup
+     */
+    if (conf.auth) {
+#if HAVE_SASL
+        int code = sasl_server_init(NULL, BROKER_SASL_NAME);
+        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));
+        }
+        QPID_LOG(info, "SASL enabled");
+#else
+        throw Exception("Requested authentication but SASL unavailable");
+#endif
+    }
+
     // Initialize plugins
     for (Plugin::Plugins::const_iterator i = plugins.begin();
          i != plugins.end();
@@ -236,6 +268,11 @@
     shutdown();
     ManagementAgent::shutdown ();
     delete store;    
+    if (config.auth) {
+#if HAVE_SASL
+        sasl_done();
+#endif
+    }
 }
 
 uint16_t Broker::getPort() const  { return getAcceptor().getPort(); }

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=647716&r1=647715&r2=647716&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 02:54:16 
2008
@@ -22,6 +22,8 @@
  *
  */
 
+#include "config.h"
+
 #include "ConnectionFactory.h"
 #include "ConnectionToken.h"
 #include "DirectExchange.h"
@@ -76,6 +78,7 @@
         uint64_t stagingThreshold;
         bool enableMgmt;
         uint16_t mgmtPubInterval;
+        bool auth;
         uint32_t ack;
     };
     
@@ -109,6 +112,7 @@
     uint64_t getStagingThreshold() { return config.stagingThreshold; }
     DtxManager& getDtxManager() { return dtxManager; }
     DataDir& getDataDir() { return dataDir; }
+    Options& getOptions() { return config; }
 
     SessionManager& getSessionManager() { return sessionManager; }
     PreviewSessionManager& getPreviewSessionManager() { return 
previewSessionManager; }

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=647716&r1=647715&r2=647716&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 02:54:16 2008
@@ -18,6 +18,9 @@
  * under the License.
  *
  */
+
+#include "config.h"
+
 #include "PreviewConnection.h"
 #include "SessionState.h"
 #include "BrokerAdapter.h"
@@ -36,6 +39,10 @@
 #include <iostream>
 #include <assert.h>
 
+#if HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 using namespace boost;
 using namespace qpid::sys;
 using namespace qpid::framing;
@@ -87,6 +94,9 @@
 
 PreviewConnection::PreviewConnection(ConnectionOutputHandler* out_, Broker& 
broker_, const std::string& mgmtId_, bool isLink) :
     ConnectionState(out_, broker_),
+#if HAVE_SASL
+    sasl_conn(NULL),
+#endif
     adapter(*this, isLink),
     mgmtClosing(false),
     mgmtId(mgmtId_)
@@ -108,7 +118,14 @@
     }
 }
 
-PreviewConnection::~PreviewConnection () {}
+PreviewConnection::~PreviewConnection () {
+#if HAVE_LIBSASL2
+    if (NULL != sasl_conn) {
+        sasl_dispose(&sasl_conn);
+        sasl_conn = NULL;
+    }
+#endif
+}
 
 void PreviewConnection::received(framing::AMQFrame& frame){
     if (mgmtClosing) 

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=647716&r1=647715&r2=647716&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 02:54:16 2008
@@ -21,6 +21,8 @@
 #ifndef _PreviewConnection_
 #define _PreviewConnection_
 
+#include "config.h"
+
 #include <memory>
 #include <sstream>
 #include <vector>
@@ -47,11 +49,19 @@
 
 #include <boost/ptr_container/ptr_map.hpp>
 
+#if HAVE_SASL
+#include <sasl/sasl.h>
+#endif
+
 namespace qpid {
 namespace broker {
 
 class PreviewConnection : public sys::ConnectionInputHandler, public 
ConnectionState
 {
+#if HAVE_SASL
+  friend class PreviewConnectionHandler;
+#endif
+
   public:
     PreviewConnection(sys::ConnectionOutputHandler* out, Broker& broker, const 
std::string& mgmtId, bool isLink = false);
     ~PreviewConnection ();
@@ -76,6 +86,10 @@
     management::Manageable::status_t
         ManagementMethod (uint32_t methodId, management::Args& args);
 
+  protected:
+#if HAVE_SASL
+    sasl_conn_t *sasl_conn;
+#endif
 
   private:
     typedef boost::ptr_map<framing::ChannelId, PreviewSessionHandler> 
ChannelMap;

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=647716&r1=647715&r2=647716&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 02:54:16 2008
@@ -20,11 +20,18 @@
  *
  */
 
+#include "config.h"
+
 #include "PreviewConnectionHandler.h"
 #include "PreviewConnection.h"
 #include "qpid/framing/ConnectionStartBody.h"
 #include "qpid/framing/ClientInvoker.h"
 #include "qpid/framing/ServerInvoker.h"
+#include "qpid/log/Statement.h"
+
+#if HAVE_SASL
+#include <sasl/sasl.h>
+#endif
 
 using namespace qpid;
 using namespace qpid::broker;
@@ -81,15 +88,61 @@
 {
     //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);
-            //TODO: authentication
+
+#if HAVE_SASL
+            if (connection.getBroker().getOptions().auth) {
+                int code = sasl_server_new(BROKER_SASL_NAME,
+                                           NULL, NULL, NULL, NULL, NULL, 0,
+                                           &connection.sasl_conn);
+
+                if (SASL_OK != code) {
+                    QPID_LOG(info, "SASL Plain: Connection creation failed: "
+                             << sasl_errdetail(connection.sasl_conn));
+
+                        // TODO: Change this to an exception signaling
+                        // server error, when one is available
+                    throw CommandInvalidException("Unable to perform 
authentication");
+                }
+
+                code = sasl_checkpass(connection.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(connection.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
+            }
+#endif
+
             connection.setUserId(uid);
         }
-    }
+    } 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());
 }
         

Modified: incubator/qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h?rev=647716&r1=647715&r2=647716&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/BrokerFixture.h Mon Apr 14 02:54:16 
2008
@@ -47,6 +47,7 @@
         opts.enableMgmt=false;  
         opts.workerThreads=1;
         opts.dataDir="";
+        opts.auth=false;
         broker = Broker::create(opts);
         // TODO aconway 2007-12-05: At one point BrokerFixture
         // tests could hang in Connection ctor if the following

Modified: incubator/qpid/trunk/qpid/cpp/src/tests/run_federation_tests
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/run_federation_tests?rev=647716&r1=647715&r2=647716&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/run_federation_tests (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/run_federation_tests Mon Apr 14 
02:54:16 2008
@@ -4,9 +4,9 @@
 trap stop_brokers EXIT
 
 start_brokers() {
-    ../qpidd --daemon --port 0 --no-data-dir > qpidd.port
+    ../qpidd --daemon --port 0 --no-data-dir --auth no > qpidd.port
     LOCAL_PORT=`cat qpidd.port`
-    ../qpidd --daemon --port 0 --no-data-dir > qpidd.port
+    ../qpidd --daemon --port 0 --no-data-dir --auth no > qpidd.port
     REMOTE_PORT=`cat qpidd.port`
 }
 

Modified: incubator/qpid/trunk/qpid/cpp/src/tests/start_broker
URL: 
http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/tests/start_broker?rev=647716&r1=647715&r2=647716&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/tests/start_broker (original)
+++ incubator/qpid/trunk/qpid/cpp/src/tests/start_broker Mon Apr 14 02:54:16 
2008
@@ -1,4 +1,4 @@
 #!/bin/sh
 rm -f qpidd.vglog qpidd.log
 test -n "$VALGRIND" && VALGRIND="$VALGRIND --log-file-exactly=qpidd.vglog --"
-exec libtool --mode=execute $VALGRIND ../qpidd --daemon --port 0 --log-output 
qpidd.log "$@" > qpidd.port
+exec libtool --mode=execute $VALGRIND ../qpidd --auth no --daemon --port 0 
--log-output qpidd.log "$@" > qpidd.port


Reply via email to