summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/Makefile.am3
-rw-r--r--cpp/src/qpid/broker/Broker.cpp3
-rw-r--r--cpp/src/qpid/broker/Broker.h1
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.cpp35
-rw-r--r--cpp/src/qpid/broker/SaslAuthenticator.h2
-rw-r--r--cpp/src/sasl.mk31
-rw-r--r--cpp/src/tests/ForkedBroker.cpp5
-rw-r--r--cpp/src/tests/ForkedBroker.h4
-rw-r--r--cpp/src/tests/Makefile.am11
-rw-r--r--cpp/src/tests/cluster_authentication_soak.cpp121
-rwxr-xr-xcpp/src/tests/run_cluster_authentication_soak4
-rwxr-xr-xcpp/src/tests/run_cluster_authentication_test4
-rw-r--r--cpp/src/tests/sasl_config/qpidd.conf45
13 files changed, 223 insertions, 46 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am
index f2125eb22c..f3f8ac5f1c 100644
--- a/cpp/src/Makefile.am
+++ b/cpp/src/Makefile.am
@@ -268,6 +268,7 @@ if SSL
include ssl.mk
endif
+
# New 0-10 codec, to be integrated in future.
# libqpidamqp_0_10_la_SOURCES=
EXTRA_DIST +=\
@@ -488,6 +489,8 @@ if HAVE_SASL
libqpidcommon_la_SOURCES += qpid/sys/cyrus/CyrusSecurityLayer.h
libqpidcommon_la_SOURCES += qpid/sys/cyrus/CyrusSecurityLayer.cpp
libqpidcommon_la_LIBADD += -lsasl2
+
+include sasl.mk
endif
libqpidbroker_la_LIBADD = libqpidcommon.la -luuid
diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp
index 09157c1e62..c887fa9c32 100644
--- a/cpp/src/qpid/broker/Broker.cpp
+++ b/cpp/src/qpid/broker/Broker.cpp
@@ -124,6 +124,7 @@ Broker::Options::Options(const std::string& name) :
("tcp-nodelay", optValue(tcpNoDelay), "Set TCP_NODELAY on TCP connections")
("require-encryption", optValue(requireEncrypted), "Only accept connections that are encrypted")
("known-hosts-url", optValue(knownHosts, "URL or 'none'"), "URL to send as 'known-hosts' to clients ('none' implies empty list)")
+ ("sasl-config", optValue(saslConfigPath, "FILE"), "gets sasl config from nonstandard location")
("max-session-rate", optValue(maxSessionRate, "MESSAGES/S"), "Sets the maximum message rate per session (0=unlimited)")
("async-queue-events", optValue(asyncQueueEvents, "yes|no"), "Set Queue Events async, used for services like replication");
}
@@ -263,7 +264,7 @@ Broker::Broker(const Broker::Options& conf) :
* SASL setup, can fail and terminate startup
*/
if (conf.auth) {
- SaslAuthenticator::init(qpid::saslName);
+ SaslAuthenticator::init(qpid::saslName, conf.saslConfigPath);
QPID_LOG(info, "SASL enabled");
} else {
QPID_LOG(notice, "SASL disabled: No Authentication Performed");
diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h
index f55f94bc8e..10408867dc 100644
--- a/cpp/src/qpid/broker/Broker.h
+++ b/cpp/src/qpid/broker/Broker.h
@@ -110,6 +110,7 @@ public:
bool tcpNoDelay;
bool requireEncrypted;
std::string knownHosts;
+ std::string saslConfigPath;
uint32_t maxSessionRate;
bool asyncQueueEvents;
bool qmf2Support;
diff --git a/cpp/src/qpid/broker/SaslAuthenticator.cpp b/cpp/src/qpid/broker/SaslAuthenticator.cpp
index c55f3edb38..b54eb19971 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.cpp
+++ b/cpp/src/qpid/broker/SaslAuthenticator.cpp
@@ -93,9 +93,20 @@ bool SaslAuthenticator::available(void) {
}
// Initialize the SASL mechanism; throw if it fails.
-void SaslAuthenticator::init(const std::string& saslName)
+void SaslAuthenticator::init(const std::string& saslName, std::string const & saslConfigPath )
{
- int code = sasl_server_init(NULL, saslName.c_str());
+ int code;
+ // If we are not given a specific sasl path, do
+ // nothing and allow the default to be used.
+ if ( ! saslConfigPath.empty() ) {
+ if(SASL_OK != (code=sasl_set_path(SASL_PATH_TYPE_CONFIG, const_cast<char *>(saslConfigPath.c_str())))) {
+ QPID_LOG(error, "SASL: sasl_set_path: [" << code << "] " );
+ return;
+ }
+ QPID_LOG(info, "SASL: config path set to " << saslConfigPath );
+ }
+
+ 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
@@ -224,18 +235,20 @@ void CyrusAuthenticator::init()
* which cannot specify a realm for the user that is
* authenticating.
*/
+ int code;
+
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);
+ 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));
+ QPID_LOG(error, "SASL: Connection creation failed: [" << code << "] " << sasl_errdetail(sasl_conn));
// TODO: Change this to an exception signaling
// server error, when one is available
diff --git a/cpp/src/qpid/broker/SaslAuthenticator.h b/cpp/src/qpid/broker/SaslAuthenticator.h
index f4ad24b3bd..b4b946f7ce 100644
--- a/cpp/src/qpid/broker/SaslAuthenticator.h
+++ b/cpp/src/qpid/broker/SaslAuthenticator.h
@@ -58,7 +58,7 @@ public:
static bool available(void);
// Initialize the SASL mechanism; throw if it fails.
- static void init(const std::string& saslName);
+ static void init(const std::string& saslName, std::string const & saslConfigPath );
static void fini(void);
static std::auto_ptr<SaslAuthenticator> createAuthenticator(Connection& connection, bool isShadow);
diff --git a/cpp/src/sasl.mk b/cpp/src/sasl.mk
new file mode 100644
index 0000000000..58743c3ad6
--- /dev/null
+++ b/cpp/src/sasl.mk
@@ -0,0 +1,31 @@
+#
+# 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.
+#
+SASLTEST_DIR = tests/sasl_config
+SASLTEST_CONF = $(SASLTEST_DIR)/qpidd.conf
+SASLTEST_DB = $(SASLTEST_DIR)/qpidd.sasldb
+
+$(SASLTEST_DB):
+ echo zig | $(SASL_PASSWD) -c -p -f $(SASLTEST_DB) -u QPID zig
+ echo zag | $(SASL_PASSWD) -c -p -f $(SASLTEST_DB) -u QPID zag
+
+sasltestdbdir = $(SASLTEST_DIR)
+sasltestdb_DATA = $(SASLTEST_DB)
+
+CLEANFILES=$(SASLTEST_DB)
+
diff --git a/cpp/src/tests/ForkedBroker.cpp b/cpp/src/tests/ForkedBroker.cpp
index 529774df98..0aedb50ec1 100644
--- a/cpp/src/tests/ForkedBroker.cpp
+++ b/cpp/src/tests/ForkedBroker.cpp
@@ -40,7 +40,7 @@ return o;
namespace qpid {
namespace tests {
-ForkedBroker::ForkedBroker(const Args& constArgs) {
+ForkedBroker::ForkedBroker(const Args& constArgs) : running(false), exitStatus(0) {
Args args(constArgs);
Args::iterator i = find(args.begin(), args.end(), string("TMP_DATA_DIR"));
if (i != args.end()) {
@@ -79,6 +79,8 @@ void ForkedBroker::kill(int sig) {
throw ErrnoException("wait for forked process failed");
if (WEXITSTATUS(status) != 0 && sig != 9)
throw qpid::Exception(QPID_MSG("Forked broker exited with: " << WEXITSTATUS(status)));
+ running = false;
+ exitStatus = status;
}
bool isLogOption(const std::string& s) {
@@ -122,6 +124,7 @@ void ForkedBroker::init(const Args& userArgs) {
else throw qpid::Exception("EOF reading port number from child.");
}
::close(pipeFds[0]);
+ running = true;
}
else { // child
::close(pipeFds[0]);
diff --git a/cpp/src/tests/ForkedBroker.h b/cpp/src/tests/ForkedBroker.h
index ddbad185d8..87e141a425 100644
--- a/cpp/src/tests/ForkedBroker.h
+++ b/cpp/src/tests/ForkedBroker.h
@@ -63,11 +63,15 @@ class ForkedBroker {
int wait(); // Wait for exit, return exit status.
uint16_t getPort() { return port; }
pid_t getPID() { return pid; }
+ bool isRunning() { return running; }
private:
void init(const Args& args);
+ bool running;
+ int exitStatus;
+
pid_t pid;
int port;
std::string dataDir;
diff --git a/cpp/src/tests/Makefile.am b/cpp/src/tests/Makefile.am
index 92e4e858f7..99b226b004 100644
--- a/cpp/src/tests/Makefile.am
+++ b/cpp/src/tests/Makefile.am
@@ -314,7 +314,7 @@ TESTS_ENVIRONMENT = \
$(srcdir)/run_test
system_tests = qpid-client-test quick_perftest quick_topictest run_header_test quick_txtest
-TESTS += start_broker $(system_tests) python_tests stop_broker run_federation_tests run_acl_tests run_cli_tests replication_test
+TESTS += start_broker $(system_tests) python_tests stop_broker run_federation_tests run_acl_tests run_cli_tests replication_test run_cluster_authentication_test
EXTRA_DIST += \
run_test vg_check \
@@ -351,7 +351,8 @@ EXTRA_DIST += \
run_test.ps1 \
start_broker.ps1 \
stop_broker.ps1 \
- topictest.ps1
+ topictest.ps1 \
+ run_cluster_authentication_test
check_LTLIBRARIES += libdlclose_noop.la
libdlclose_noop_la_LDFLAGS = -module -rpath $(abs_builddir)
@@ -364,7 +365,8 @@ CLEANFILES+=valgrind.out *.log *.vglog* dummy_test qpidd.port $(unit_wrappers)
LONG_TESTS+=start_broker fanout_perftest shared_perftest multiq_perftest topic_perftest run_ring_queue_test stop_broker \
run_failover_soak reliable_replication_test \
- federated_cluster_test_with_node_failure
+ federated_cluster_test_with_node_failure \
+ run_cluster_authentication_soak
EXTRA_DIST+= \
fanout_perftest \
@@ -373,7 +375,8 @@ EXTRA_DIST+= \
topic_perftest \
run_failover_soak \
reliable_replication_test \
- federated_cluster_test_with_node_failure
+ federated_cluster_test_with_node_failure \
+ run_cluster_authentication_soak
check-long:
$(MAKE) check TESTS="$(LONG_TESTS)" VALGRIND=
diff --git a/cpp/src/tests/cluster_authentication_soak.cpp b/cpp/src/tests/cluster_authentication_soak.cpp
index ccf4d278c0..6963438d5f 100644
--- a/cpp/src/tests/cluster_authentication_soak.cpp
+++ b/cpp/src/tests/cluster_authentication_soak.cpp
@@ -44,6 +44,10 @@
#include <qpid/client/Connection.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
@@ -64,32 +68,42 @@ typedef vector<ForkedBroker *> brokerVector;
-int newbiePort = 0;
+int runSilent = 1;
+int newbiePort = 0;
+
+void
+makeClusterName ( string & s ) {
+ stringstream ss;
+ ss << "authenticationSoakCluster_" << Uuid(true).str();
+ s = ss.str();
+}
void
-startBroker ( brokerVector & brokers ,
- int brokerNumber ) {
- stringstream portSS, prefix;
+startBroker ( brokerVector & brokers , int brokerNumber, string const & clusterName ) {
+ stringstream prefix, clusterArg;
prefix << "soak-" << brokerNumber;
+ clusterArg << "--cluster-name=" << clusterName;
+
std::vector<std::string> argv;
argv.push_back ("../qpidd");
argv.push_back ("--no-module-dir");
argv.push_back ("--load-module=../.libs/cluster.so");
- argv.push_back ("--cluster-name=micks_test_cluster");
- argv.push_back ("--cluster-username=guest");
- argv.push_back ("--cluster-password=guest");
+ argv.push_back (clusterArg.str().c_str());
+ argv.push_back ("--cluster-username=zig");
+ argv.push_back ("--cluster-password=zig");
argv.push_back ("--cluster-mechanism=ANONYMOUS");
- argv.push_back ("TMP_DATA_DIR");
+ argv.push_back ("--sasl-config=./sasl_config");
argv.push_back ("--auth=yes");
argv.push_back ("--mgmt-enable=yes");
argv.push_back ("--log-prefix");
argv.push_back (prefix.str());
argv.push_back ("--log-to-file");
argv.push_back (prefix.str()+".log");
+ argv.push_back ("TMP_DATA_DIR");
ForkedBroker * newbie = new ForkedBroker (argv);
newbiePort = newbie->getPort();
@@ -100,7 +114,7 @@ startBroker ( brokerVector & brokers ,
bool
-runPerftest ( ) {
+runPerftest ( bool hangTest ) {
stringstream portSs;
portSs << newbiePort;
@@ -111,9 +125,9 @@ runPerftest ( ) {
argv.push_back ( "-p" );
argv.push_back ( portSs.str().c_str() );
argv.push_back ( "--username" );
- argv.push_back ( "guest" );
+ argv.push_back ( "zig" );
argv.push_back ( "--password" );
- argv.push_back ( "guest" );
+ argv.push_back ( "zig" );
argv.push_back ( "--mechanism" );
argv.push_back ( "DIGEST-MD5" );
argv.push_back ( "--count" );
@@ -133,6 +147,12 @@ runPerftest ( ) {
return false;
}
else {
+ if ( hangTest ) {
+ if ( ! runSilent )
+ cerr << "Pausing perftest " << pid << endl;
+ kill ( pid, 19 );
+ }
+
struct timeval startTime,
currentTime,
duration;
@@ -140,7 +160,7 @@ runPerftest ( ) {
gettimeofday ( & startTime, 0 );
while ( 1 ) {
- sleep ( 5 );
+ sleep ( 2 );
int status;
int returned_pid = waitpid ( pid, &status, WNOHANG );
if ( returned_pid == pid ) {
@@ -171,14 +191,9 @@ runPerftest ( ) {
bool
allBrokersAreAlive ( brokerVector & brokers ) {
- for ( unsigned int i = 0; i < brokers.size(); ++ i ) {
- pid_t pid = brokers[i]->getPID();
- int status;
- int value;
- if ( (value = waitpid ( pid, &status, WNOHANG ) ) ) {
- return false;
- }
- }
+ for ( unsigned int i = 0; i < brokers.size(); ++ i )
+ if ( ! brokers[i]->isRunning() )
+ return false;
return true;
}
@@ -186,10 +201,23 @@ allBrokersAreAlive ( brokerVector & brokers ) {
+
void
killAllBrokers ( brokerVector & brokers ) {
- for ( unsigned int i = 0; i < brokers.size(); ++ i )
+ for ( unsigned int i = 0; i < brokers.size(); ++ i ) {
brokers[i]->kill ( 9 );
+ }
+}
+
+
+
+
+void
+killOneBroker ( brokerVector & brokers ) {
+ int doomedBroker = getpid() % brokers.size();
+ cout << "Killing broker " << brokers[doomedBroker]->getPID() << endl;
+ brokers[doomedBroker]->kill ( 9 );
+ sleep ( 2 );
}
@@ -201,15 +229,36 @@ using namespace qpid::tests;
+/*
+ * Please note that this test has self-test capability.
+ * It is intended to detect
+ * 1. perftest hangs.
+ * 2. broker deaths
+ * Both of these condtions can be forced when running manually
+ * to ensure that the test really does detect them.
+ * See command-line arguments 3 and 4.
+ */
int
main ( int argc, char ** argv )
{
- int n_iterations = argc > 0 ? atoi(argv[1]) : 1;
+ int n_iterations = argc > 1 ? atoi(argv[1]) : 1;
+ runSilent = argc > 2 ? atoi(argv[2]) : 1; // default to silent
+ int killBroker = argc > 3 ? atoi(argv[3]) : 0; // Force the kill of one broker.
+ int hangTest = argc > 4 ? atoi(argv[4]) : 0; // Force the first perftest to hang.
int n_brokers = 3;
brokerVector brokers;
+ #ifndef HAVE_SASL
+ if ( ! runSilent )
+ cout << "No SASL support. cluster_authentication_soak disabled.";
+ return 0;
+ #endif
+
+ srand ( getpid() );
+ string clusterName;
+ makeClusterName ( clusterName );
for ( int i = 0; i < n_brokers; ++ i ) {
- startBroker ( brokers, i );
+ startBroker ( brokers, i, clusterName );
}
sleep ( 3 );
@@ -221,22 +270,38 @@ main ( int argc, char ** argv )
* set to 1.
*/
for ( int iteration = 0; iteration < n_iterations; ++ iteration ) {
- if ( ! runPerftest ( ) ) {
- cerr << "qpid-perftest " << iteration << " failed.\n";
+ if ( ! runPerftest ( hangTest ) ) {
+ if ( ! runSilent )
+ cerr << "qpid-perftest " << iteration << " failed.\n";
return 1;
}
if ( ! ( iteration % 10 ) ) {
- cerr << "qpid-perftest " << iteration << " complete. -------------- \n";
+ if ( ! runSilent )
+ cerr << "qpid-perftest " << iteration << " complete. -------------- \n";
}
}
- cerr << "\nqpid-perftest " << n_iterations << " iterations complete. -------------- \n\n";
+ if ( ! runSilent )
+ cerr << "\nqpid-perftest " << n_iterations << " iterations complete. -------------- \n\n";
+
+ /* If the command-line tells us to kill a broker, do
+ * it now. Use this option to prove that this test
+ * really can detect broker-deaths.
+ */
+ if ( killBroker ) {
+ killOneBroker ( brokers );
+ }
if ( ! allBrokersAreAlive ( brokers ) ) {
- cerr << "not all brokers are alive.\n";
+ if ( ! runSilent )
+ cerr << "not all brokers are alive.\n";
+ killAllBrokers ( brokers );
return 2;
}
killAllBrokers ( brokers );
+ if ( ! runSilent )
+ cout << "success.\n";
+
return 0;
}
diff --git a/cpp/src/tests/run_cluster_authentication_soak b/cpp/src/tests/run_cluster_authentication_soak
new file mode 100755
index 0000000000..d0a9059097
--- /dev/null
+++ b/cpp/src/tests/run_cluster_authentication_soak
@@ -0,0 +1,4 @@
+#! /bin/bash
+
+./cluster_authentication_soak 500
+
diff --git a/cpp/src/tests/run_cluster_authentication_test b/cpp/src/tests/run_cluster_authentication_test
new file mode 100755
index 0000000000..5e71baf2e5
--- /dev/null
+++ b/cpp/src/tests/run_cluster_authentication_test
@@ -0,0 +1,4 @@
+#! /bin/bash
+
+./cluster_authentication_soak
+
diff --git a/cpp/src/tests/sasl_config/qpidd.conf b/cpp/src/tests/sasl_config/qpidd.conf
new file mode 100644
index 0000000000..62fd8d4dee
--- /dev/null
+++ b/cpp/src/tests/sasl_config/qpidd.conf
@@ -0,0 +1,45 @@
+#
+# 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.
+#
+#
+# This configuation allows for either SASL PLAIN or ANONYMOUS
+# authentication. The PLAIN authentication is done on a
+# username+password, which is stored in the sasldb_path
+# file. Usernames and passwords can be added to the file using the
+# command:
+#
+# saslpasswd2 -f /var/lib/qpidd/qpidd.sasldb -u <REALM> <USER>
+#
+# The REALM is important and should be the same as the --auth-realm
+# option to the broker. This lets the broker properly find the user in
+# the sasldb file.
+#
+# Existing user accounts may be listed with:
+#
+# sasldblistusers2 -f /var/lib/qpidd/qpidd.sasldb
+#
+# NOTE: The sasldb file must be readable by the user running the qpidd
+# daemon, and should be readable only by that user.
+#
+pwcheck_method: auxprop
+auxprop_plugin: sasldb
+sasldb_path: ./sasl_config/qpidd.sasldb
+
+#following line stops spurious 'sql_select option missing' errors when
+#cyrus-sql-sasl plugin is installed
+sql_select: dummy select