diff --git a/cpp/demo/IceGrid/secure/README b/cpp/demo/IceGrid/secure/README
index 3fa12aa..e15cf71 100644
--- a/cpp/demo/IceGrid/secure/README
+++ b/cpp/demo/IceGrid/secure/README
@@ -31,9 +31,10 @@ so you might as well use a certificate without a password and rely on
the filesystem permissions to restrict access to the certificate.
Once the certificates are generated, you can start the IceGrid
-registry, node, and Glacier2 router:
+registries, node, and Glacier2 router:
-$ icegridregistry --Ice.Config=config.registry
+$ icegridregistry --Ice.Config=config.master
+$ icegridregistry --Ice.Config=config.slave
$ icegridnode --Ice.Config=config.node
$ glacier2router --Ice.Config=config.glacier2
diff --git a/cpp/demo/IceGrid/secure/application.xml b/cpp/demo/IceGrid/secure/application.xml
index 1da08d8..741c599 100644
--- a/cpp/demo/IceGrid/secure/application.xml
+++ b/cpp/demo/IceGrid/secure/application.xml
@@ -20,8 +20,8 @@
-
-
+
+
diff --git a/cpp/demo/IceGrid/secure/config.admin b/cpp/demo/IceGrid/secure/config.admin
index 3ae72a9..b3a5a22 100644
--- a/cpp/demo/IceGrid/secure/config.admin
+++ b/cpp/demo/IceGrid/secure/config.admin
@@ -14,7 +14,7 @@ IceGridAdmin.Password=dummy
# SSL Configuration
#
IceSSL.DefaultDir=certs
-IceSSL.TrustOnly.Client=CN="IceGrid Registry";CN="Glacier2"
+IceSSL.TrustOnly.Client=CN="Master";CN="Slave";CN="Glacier2"
# C++ configuration
Ice.Plugin.IceSSL.cpp=IceSSL:createIceSSL
diff --git a/cpp/demo/IceGrid/secure/config.client b/cpp/demo/IceGrid/secure/config.client
index 3ea6283..f5d45bc 100644
--- a/cpp/demo/IceGrid/secure/config.client
+++ b/cpp/demo/IceGrid/secure/config.client
@@ -1,7 +1,7 @@
#
# The IceGrid locator proxy.
#
-Ice.Default.Locator=DemoIceGrid/Locator:tcp -p 4061
+Ice.Default.Locator=DemoIceGrid/Locator:tcp -p 4061:tcp -p 14061
#
# Trace properties.
diff --git a/cpp/demo/IceGrid/secure/config.master b/cpp/demo/IceGrid/secure/config.master
new file mode 100644
index 0000000..95cba08
--- /dev/null
+++ b/cpp/demo/IceGrid/secure/config.master
@@ -0,0 +1,61 @@
+#
+# The IceGrid instance name.
+#
+IceGrid.InstanceName=DemoIceGrid
+
+#
+# IceGrid registry configuration.
+#
+IceGrid.Registry.Client.Endpoints=tcp -p 4061 -t 10000:ssl -p 4062 -t 10000
+IceGrid.Registry.Server.Endpoints=ssl -t 10000
+IceGrid.Registry.Internal.Endpoints=ssl -t 10000
+IceGrid.Registry.Data=db/master
+
+#
+# Ensure that nodes and slaves connecting to this registry have a name
+# matching the certificate CN.
+#
+IceGrid.Registry.RequireNodeCertCN=1
+IceGrid.Registry.RequireReplicaCertCN=1
+
+#
+# IceGrid admin clients must use a secure connection to connect to the
+# registry or use Glacier2.
+#
+IceGrid.Registry.AdminSessionManager.Endpoints=ssl -t 10000
+IceGrid.Registry.AdminPermissionsVerifier=DemoIceGrid/NullPermissionsVerifier
+
+#
+# IceGrid SQL configuration if using SQL database.
+#
+#Ice.Plugin.DB=IceGridSqlDB:createSqlDB
+#IceGrid.SQL.DatabaseType=QSQLITE
+#IceGrid.SQL.DatabaseName=db/master/Registry.db
+
+#
+# Trace properties.
+#
+Ice.ProgramName=Master
+IceGrid.Registry.Trace.Node=2
+IceGrid.Registry.Trace.Replica=2
+
+#
+# SSL Configuration
+#
+Ice.Plugin.IceSSL=IceSSL:createIceSSL
+IceSSL.DefaultDir=certs
+IceSSL.CertAuthFile=ca_cert.pem
+IceSSL.CertFile=master_cert.pem
+IceSSL.KeyFile=master_key.pem
+
+#
+# Don't require certificates. This is useful for admin clients that don't
+# use certificate but still need to establish a secure connection for the
+# username/password authentication
+#
+IceSSL.VerifyPeer=1
+
+IceSSL.TrustOnly.Client=CN="Master";CN="Slave";CN="Node";CN="Glacier2"
+IceSSL.TrustOnly.Server.IceGrid.Registry.Server=CN="Server"
+IceSSL.TrustOnly.Server.IceGrid.Registry.Internal=CN="Node";CN="Master";CN="Slave"
+IceSSL.TrustOnly.Server.IceGrid.Registry.AdminSessionManager=CN="Glacier2"
diff --git a/cpp/demo/IceGrid/secure/config.node b/cpp/demo/IceGrid/secure/config.node
index 9629a09..17e9911 100644
--- a/cpp/demo/IceGrid/secure/config.node
+++ b/cpp/demo/IceGrid/secure/config.node
@@ -1,7 +1,7 @@
#
# The IceGrid locator proxy.
#
-Ice.Default.Locator=DemoIceGrid/Locator:ssl -p 4062 -t 10000
+Ice.Default.Locator=DemoIceGrid/Locator:ssl -p 4062 -t 10000:ssl -p 14062 -t 10000
#
# IceGrid node configuration.
@@ -26,5 +26,5 @@ IceSSL.CertAuthFile=ca_cert.pem
IceSSL.CertFile=node_cert.pem
IceSSL.KeyFile=node_key.pem
-IceSSL.TrustOnly.Client=CN="Server";CN="IceGrid Registry"
-IceSSL.TrustOnly.Server=CN="IceGrid Registry"
+IceSSL.TrustOnly.Client=CN="Server";CN="Master";CN="Slave"
+IceSSL.TrustOnly.Server=CN="Master";CN="Slave"
diff --git a/cpp/demo/IceGrid/secure/config.registry b/cpp/demo/IceGrid/secure/config.registry
deleted file mode 100644
index 84b42ed..0000000
--- a/cpp/demo/IceGrid/secure/config.registry
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# The IceGrid instance name.
-#
-IceGrid.InstanceName=DemoIceGrid
-
-#
-# IceGrid registry configuration.
-#
-IceGrid.Registry.Client.Endpoints=tcp -p 4061 -t 10000:ssl -p 4062 -t 10000
-IceGrid.Registry.Server.Endpoints=ssl -t 10000
-IceGrid.Registry.Internal.Endpoints=ssl -t 10000
-IceGrid.Registry.Data=db/registry
-
-#
-# IceGrid admin clients must use a secure connection to connect to the
-# registry or use Glacier2.
-#
-IceGrid.Registry.AdminSessionManager.Endpoints=ssl -t 10000
-IceGrid.Registry.AdminPermissionsVerifier=DemoIceGrid/NullPermissionsVerifier
-
-#
-# IceGrid SQL configuration if using SQL database.
-#
-#Ice.Plugin.DB=IceGridSqlDB:createSqlDB
-#IceGrid.SQL.DatabaseType=QSQLITE
-#IceGrid.SQL.DatabaseName=db/registry/Registry.db
-
-#
-# Trace properties.
-#
-Ice.ProgramName=Registry
-IceGrid.Registry.Trace.Node=2
-IceGrid.Registry.Trace.Replica=2
-
-#
-# SSL Configuration
-#
-Ice.Plugin.IceSSL=IceSSL:createIceSSL
-IceSSL.DefaultDir=certs
-IceSSL.CertAuthFile=ca_cert.pem
-IceSSL.CertFile=registry_cert.pem
-IceSSL.KeyFile=registry_key.pem
-
-#
-# Don't require certificates. This is useful for admin clients that don't
-# use certificate but still need to establish a secure connection for the
-# username/password authentication
-#
-IceSSL.VerifyPeer=1
-
-IceSSL.TrustOnly.Client=CN="IceGrid Registry";CN="IceGrid Node";CN="Glacier2"
-IceSSL.TrustOnly.Server.IceGrid.Registry.Server=CN="Server"
-IceSSL.TrustOnly.Server.IceGrid.Registry.Internal=CN="IceGrid Node";CN="IceGrid Registry"
-IceSSL.TrustOnly.Server.IceGrid.Registry.AdminSessionManager=CN="Glacier2"
diff --git a/cpp/demo/IceGrid/secure/config.slave b/cpp/demo/IceGrid/secure/config.slave
new file mode 100644
index 0000000..3de35ef
--- /dev/null
+++ b/cpp/demo/IceGrid/secure/config.slave
@@ -0,0 +1,66 @@
+#
+# The IceGrid locator proxy.
+#
+Ice.Default.Locator=DemoIceGrid/Locator:ssl -p 4062 -t 10000
+
+#
+# The IceGrid instance name.
+#
+IceGrid.InstanceName=DemoIceGrid
+
+#
+# IceGrid registry configuration.
+#
+IceGrid.Registry.Client.Endpoints=tcp -p 14061 -t 10000:ssl -p 14062 -t 10000
+IceGrid.Registry.Server.Endpoints=ssl -t 10000
+IceGrid.Registry.Internal.Endpoints=ssl -t 10000
+IceGrid.Registry.Data=db/slave
+IceGrid.Registry.ReplicaName=Slave
+
+#
+# Ensure that nodes connecting to this registry have a name matching
+# the certificate CN.
+#
+IceGrid.Registry.RequireNodeCertCN=1
+
+#
+# IceGrid admin clients must use a secure connection to connect to the
+# registry or use Glacier2.
+#
+IceGrid.Registry.AdminSessionManager.Endpoints=ssl -t 10000
+IceGrid.Registry.AdminPermissionsVerifier=DemoIceGrid/NullPermissionsVerifier
+
+#
+# IceGrid SQL configuration if using SQL database.
+#
+#Ice.Plugin.DB=IceGridSqlDB:createSqlDB
+#IceGrid.SQL.DatabaseType=QSQLITE
+#IceGrid.SQL.DatabaseName=db/slave/Registry.db
+
+#
+# Trace properties.
+#
+Ice.ProgramName=Slave
+IceGrid.Registry.Trace.Node=2
+IceGrid.Registry.Trace.Replica=2
+
+#
+# SSL Configuration
+#
+Ice.Plugin.IceSSL=IceSSL:createIceSSL
+IceSSL.DefaultDir=certs
+IceSSL.CertAuthFile=ca_cert.pem
+IceSSL.CertFile=slave_cert.pem
+IceSSL.KeyFile=slave_key.pem
+
+#
+# Don't require certificates. This is useful for admin clients that don't
+# use certificate but still need to establish a secure connection for the
+# username/password authentication
+#
+IceSSL.VerifyPeer=1
+
+IceSSL.TrustOnly.Client=CN="Master";CN="Slave";CN="Node";CN="Glacier2"
+IceSSL.TrustOnly.Server.IceGrid.Registry.Server=CN="Server"
+IceSSL.TrustOnly.Server.IceGrid.Registry.Internal=CN="Node";CN="Master";CN="Slave"
+IceSSL.TrustOnly.Server.IceGrid.Registry.AdminSessionManager=CN="Glacier2"
diff --git a/cpp/demo/IceGrid/secure/makecerts.py b/cpp/demo/IceGrid/secure/makecerts.py
index 2f95d04..6d49467 100755
--- a/cpp/demo/IceGrid/secure/makecerts.py
+++ b/cpp/demo/IceGrid/secure/makecerts.py
@@ -44,8 +44,9 @@ runIceca("init --overwrite --no-password")
print
print
-createCertificate("registry", "IceGrid Registry")
-createCertificate("node", "IceGrid Node")
+createCertificate("master", "Master")
+createCertificate("slave", "Slave")
+createCertificate("node", "Node")
createCertificate("glacier2", "Glacier2")
createCertificate("server", "Server")
diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp
index 337a129..202e970 100644
--- a/cpp/src/Ice/PropertyNames.cpp
+++ b/cpp/src/Ice/PropertyNames.cpp
@@ -8,7 +8,7 @@
// **********************************************************************
//
-// Generated by makeprops.py from file ..\config\PropertyNames.xml, Mon May 09 07:39:43 2011
+// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Jul 12 07:22:34 2011
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
@@ -335,6 +335,8 @@ const IceInternal::Property IceGridPropsData[] =
IceInternal::Property("IceGrid.Registry.PermissionsVerifier", false, 0),
IceInternal::Property("IceGrid.Registry.ReplicaName", false, 0),
IceInternal::Property("IceGrid.Registry.ReplicaSessionTimeout", false, 0),
+ IceInternal::Property("IceGrid.Registry.RequireNodeCertCN", false, 0),
+ IceInternal::Property("IceGrid.Registry.RequireReplicaCertCN", false, 0),
IceInternal::Property("IceGrid.Registry.Server.ACM", false, 0),
IceInternal::Property("IceGrid.Registry.Server.AdapterId", false, 0),
IceInternal::Property("IceGrid.Registry.Server.Endpoints", false, 0),
diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h
index 23a715e..e34b528 100644
--- a/cpp/src/Ice/PropertyNames.h
+++ b/cpp/src/Ice/PropertyNames.h
@@ -8,7 +8,7 @@
// **********************************************************************
//
-// Generated by makeprops.py from file ..\config\PropertyNames.xml, Mon May 09 07:39:43 2011
+// Generated by makeprops.py from file ../config/PropertyNames.xml, Tue Jul 12 07:22:34 2011
// IMPORTANT: Do not edit this file -- any edits made here will be lost!
diff --git a/cpp/src/IceGrid/Internal.ice b/cpp/src/IceGrid/Internal.ice
index 3d2faf1..6c32f9c 100644
--- a/cpp/src/IceGrid/Internal.ice
+++ b/cpp/src/IceGrid/Internal.ice
@@ -702,7 +702,7 @@ interface InternalRegistry extends FileReader
*
**/
NodeSession* registerNode(InternalNodeInfo info, Node* prx, LoadInfo loadInf)
- throws NodeActiveException;
+ throws NodeActiveException, PermissionDeniedException;
/**
*
@@ -721,7 +721,7 @@ interface InternalRegistry extends FileReader
*
**/
ReplicaSession* registerReplica(InternalReplicaInfo info, InternalRegistry* prx)
- throws ReplicaActiveException;
+ throws ReplicaActiveException, PermissionDeniedException;
/**
*
diff --git a/cpp/src/IceGrid/InternalRegistryI.cpp b/cpp/src/IceGrid/InternalRegistryI.cpp
index 61178ec..1d4def0 100644
--- a/cpp/src/IceGrid/InternalRegistryI.cpp
+++ b/cpp/src/IceGrid/InternalRegistryI.cpp
@@ -19,6 +19,8 @@
#include
#include
#include
+#include
+#include
using namespace std;
using namespace IceGrid;
@@ -38,6 +40,8 @@ InternalRegistryI::InternalRegistryI(const RegistryIPtr& registry,
Ice::PropertiesPtr properties = database->getCommunicator()->getProperties();
_nodeSessionTimeout = properties->getPropertyAsIntWithDefault("IceGrid.Registry.NodeSessionTimeout", 30);
_replicaSessionTimeout = properties->getPropertyAsIntWithDefault("IceGrid.Registry.ReplicaSessionTimeout", 30);
+ _requireNodeCertCN = properties->getPropertyAsIntWithDefault("IceGrid.Registry.RequireNodeCertCN", 0);
+ _requireReplicaCertCN = properties->getPropertyAsIntWithDefault("IceGrid.Registry.RequireReplicaCertCN", 0);
}
InternalRegistryI::~InternalRegistryI()
@@ -50,7 +54,56 @@ InternalRegistryI::registerNode(const InternalNodeInfoPtr& info,
const LoadInfo& load,
const Ice::Current& current)
{
- const Ice::LoggerPtr logger = _database->getTraceLevels()->logger;
+ const TraceLevelsPtr traceLevels = _database->getTraceLevels();
+ const Ice::LoggerPtr logger = traceLevels->logger;
+ if(!info || !node)
+ {
+ return 0;
+ }
+
+ if(_requireNodeCertCN)
+ {
+ try
+ {
+ IceSSL::ConnectionInfoPtr sslConnInfo = IceSSL::ConnectionInfoPtr::dynamicCast(current.con->getInfo());
+ if(sslConnInfo)
+ {
+ if (sslConnInfo->certs.empty() ||
+ !IceSSL::Certificate::decode(sslConnInfo->certs[0])->getSubjectDN().match("CN=" + info->name))
+ {
+ if(traceLevels->node > 0)
+ {
+ Ice::Trace out(logger, traceLevels->nodeCat);
+ out << "certificate CN doesn't match node name `" << info->name << "'";
+ }
+ throw PermissionDeniedException("certificate CN doesn't match node name `" + info->name + "'");
+ }
+ }
+ else
+ {
+ if(traceLevels->node > 0)
+ {
+ Ice::Trace out(logger, traceLevels->nodeCat);
+ out << "node certificate for `" << info->name << "' is required to connect to this registry";
+ }
+ throw PermissionDeniedException("node certificate is required to connect to this registry");
+ }
+ }
+ catch(const PermissionDeniedException& ex)
+ {
+ throw ex;
+ }
+ catch(const IceUtil::Exception&)
+ {
+ if(traceLevels->node > 0)
+ {
+ Ice::Trace out(logger, traceLevels->nodeCat);
+ out << "unexpected exception while verifying certificate for node `" << info->name << "'";
+ }
+ throw PermissionDeniedException("unable to verify certificate for node `" + info->name + "'");
+ }
+ }
+
try
{
NodeSessionIPtr session = new NodeSessionI(_database, node, info, _nodeSessionTimeout, load);
@@ -68,7 +121,56 @@ InternalRegistryI::registerReplica(const InternalReplicaInfoPtr& info,
const InternalRegistryPrx& prx,
const Ice::Current& current)
{
- const Ice::LoggerPtr logger = _database->getTraceLevels()->logger;
+ const TraceLevelsPtr traceLevels = _database->getTraceLevels();
+ const Ice::LoggerPtr logger = traceLevels->logger;
+ if(!info || !prx)
+ {
+ return 0;
+ }
+
+ if(_requireReplicaCertCN)
+ {
+ try
+ {
+ IceSSL::ConnectionInfoPtr sslConnInfo = IceSSL::ConnectionInfoPtr::dynamicCast(current.con->getInfo());
+ if(sslConnInfo)
+ {
+ if (sslConnInfo->certs.empty() ||
+ !IceSSL::Certificate::decode(sslConnInfo->certs[0])->getSubjectDN().match("CN=" + info->name))
+ {
+ if(traceLevels->replica > 0)
+ {
+ Ice::Trace out(logger, traceLevels->replicaCat);
+ out << "certificate CN doesn't match replica name `" << info->name << "'";
+ }
+ throw PermissionDeniedException("certificate CN doesn't match replica name `" + info->name + "'");
+ }
+ }
+ else
+ {
+ if(traceLevels->replica > 0)
+ {
+ Ice::Trace out(logger, traceLevels->replicaCat);
+ out << "replica certificate for `" << info->name << "' is required to connect to this registry";
+ }
+ throw PermissionDeniedException("replica certificate is required to connect to this registry");
+ }
+ }
+ catch(const PermissionDeniedException& ex)
+ {
+ throw ex;
+ }
+ catch(const IceUtil::Exception&)
+ {
+ if(traceLevels->replica > 0)
+ {
+ Ice::Trace out(logger, traceLevels->replicaCat);
+ out << "unexpected exception while verifying certificate for replica `" << info->name << "'";
+ }
+ throw PermissionDeniedException("unable to verify certificate for replica `" + info->name + "'");
+ }
+ }
+
try
{
ReplicaSessionIPtr s = new ReplicaSessionI(_database, _wellKnownObjects, info, prx, _replicaSessionTimeout);
diff --git a/cpp/src/IceGrid/InternalRegistryI.h b/cpp/src/IceGrid/InternalRegistryI.h
index 2e87a35..32f7828 100644
--- a/cpp/src/IceGrid/InternalRegistryI.h
+++ b/cpp/src/IceGrid/InternalRegistryI.h
@@ -68,6 +68,8 @@ private:
ReplicaSessionManager& _session;
int _nodeSessionTimeout;
int _replicaSessionTimeout;
+ bool _requireNodeCertCN;
+ bool _requireReplicaCertCN;
};
};
diff --git a/cpp/src/IceGrid/NodeSessionManager.cpp b/cpp/src/IceGrid/NodeSessionManager.cpp
index 792d8bd..a10ab10 100644
--- a/cpp/src/IceGrid/NodeSessionManager.cpp
+++ b/cpp/src/IceGrid/NodeSessionManager.cpp
@@ -110,6 +110,14 @@ NodeSessionKeepAliveThread::createSession(InternalRegistryPrx& registry, IceUtil
}
exception.reset(ex.ice_clone());
}
+ catch(const PermissionDeniedException& ex)
+ {
+ if(traceLevels)
+ {
+ traceLevels->logger->error("connection to the the registry `" + _name + "' was denied:\n" + ex.reason);
+ }
+ exception.reset(ex.ice_clone());
+ }
catch(const Ice::Exception& ex)
{
exception.reset(ex.ice_clone());
diff --git a/cpp/src/IceGrid/ReplicaSessionManager.cpp b/cpp/src/IceGrid/ReplicaSessionManager.cpp
index 57997d6..b2114dc 100644
--- a/cpp/src/IceGrid/ReplicaSessionManager.cpp
+++ b/cpp/src/IceGrid/ReplicaSessionManager.cpp
@@ -500,6 +500,14 @@ ReplicaSessionManager::createSession(InternalRegistryPrx& registry, IceUtil::Tim
}
exception.reset(ex.ice_clone());
}
+ catch(const PermissionDeniedException& ex)
+ {
+ if(_traceLevels)
+ {
+ _traceLevels->logger->error("connection to the the registry `" + _name + "' was denied:\n" + ex.reason);
+ }
+ exception.reset(ex.ice_clone());
+ }
catch(const Ice::Exception& ex)
{
exception.reset(ex.ice_clone());