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());