summaryrefslogtreecommitdiff
path: root/cpp/src/IceSSL/TrustManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceSSL/TrustManager.cpp')
-rw-r--r--cpp/src/IceSSL/TrustManager.cpp248
1 files changed, 248 insertions, 0 deletions
diff --git a/cpp/src/IceSSL/TrustManager.cpp b/cpp/src/IceSSL/TrustManager.cpp
new file mode 100644
index 00000000000..0ec6e285135
--- /dev/null
+++ b/cpp/src/IceSSL/TrustManager.cpp
@@ -0,0 +1,248 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceSSL/TrustManager.h>
+#include <IceSSL/RFC2253.h>
+
+#include <Ice/Properties.h>
+#include <Ice/Communicator.h>
+#include <Ice/LocalException.h>
+#include <Ice/Logger.h>
+#include <Ice/LoggerUtil.h>
+#include <Ice/Network.h>
+
+using namespace std;
+using namespace IceSSL;
+
+IceUtil::Shared* IceInternal::upCast(IceSSL::TrustManager* p) { return p; }
+
+TrustManager::TrustManager(const Ice::CommunicatorPtr& communicator) :
+ _communicator(communicator)
+{
+ Ice::PropertiesPtr properties = communicator->getProperties();
+ _traceLevel = properties->getPropertyAsInt("IceSSL.Trace.Security");
+ string key;
+ try
+ {
+ key = "IceSSL.TrustOnly";
+ parse(properties->getProperty(key), _rejectAll, _acceptAll);
+ key = "IceSSL.TrustOnly.Client";
+ parse(properties->getProperty(key), _rejectClient, _acceptClient);
+ key = "IceSSL.TrustOnly.Server";
+ parse(properties->getProperty(key), _rejectAllServer, _acceptAllServer);
+ Ice::PropertyDict dict = properties->getPropertiesForPrefix("IceSSL.TrustOnly.Server.");
+ for(Ice::PropertyDict::const_iterator p = dict.begin(); p != dict.end(); ++p)
+ {
+ string name = p->first.substr(string("IceSSL.TrustOnly.Server.").size());
+ key = p->first;
+ list<DistinguishedName> reject, accept;
+ parse(p->second, reject, accept);
+ if(!reject.empty())
+ {
+ _rejectServer[name] = reject;
+ }
+ if(!accept.empty())
+ {
+ _acceptServer[name] = accept;
+ }
+ }
+ }
+ catch(const ParseException& e)
+ {
+ Ice::PluginInitializationException ex(__FILE__, __LINE__);
+ ex.reason = "IceSSL: invalid property " + key + ":\n" + e.reason;
+ throw ex;
+ }
+}
+
+bool
+TrustManager::verify(const NativeConnectionInfoPtr& info)
+{
+ list<list<DistinguishedName> > reject, accept;
+
+ if(_rejectAll.size() > 0)
+ {
+ reject.push_back(_rejectAll);
+ }
+ if(info->incoming)
+ {
+ if(_rejectAllServer.size() > 0)
+ {
+ reject.push_back(_rejectAllServer);
+ }
+ if(info->adapterName.size() > 0)
+ {
+ map<string, list<DistinguishedName> >::const_iterator p = _rejectServer.find(info->adapterName);
+ if(p != _rejectServer.end())
+ {
+ reject.push_back(p->second);
+ }
+ }
+ }
+ else
+ {
+ if(_rejectClient.size() > 0)
+ {
+ reject.push_back(_rejectClient);
+ }
+ }
+
+ if(_acceptAll.size() > 0)
+ {
+ accept.push_back(_acceptAll);
+ }
+ if(info->incoming)
+ {
+ if(_acceptAllServer.size() > 0)
+ {
+ accept.push_back(_acceptAllServer);
+ }
+ if(info->adapterName.size() > 0)
+ {
+ map<string, list<DistinguishedName> >::const_iterator p = _acceptServer.find(info->adapterName);
+ if(p != _acceptServer.end())
+ {
+ accept.push_back(p->second);
+ }
+ }
+ }
+ else
+ {
+ if(_acceptClient.size() > 0)
+ {
+ accept.push_back(_acceptClient);
+ }
+ }
+
+ //
+ // If there is nothing to match against, then we accept the cert.
+ //
+ if(reject.empty() && accept.empty())
+ {
+ return true;
+ }
+
+ //
+ // If there is no certificate then we match false.
+ //
+ if(info->nativeCerts.size() != 0)
+ {
+ DistinguishedName subject = info->nativeCerts[0]->getSubjectDN();
+ if(_traceLevel > 0)
+ {
+ Ice::Trace trace(_communicator->getLogger(), "Security");
+ if(info->incoming)
+ {
+ trace << "trust manager evaluating client:\n"
+ << "subject = " << string(subject) << '\n'
+ << "adapter = " << info->adapterName << '\n'
+ << "local addr = " << info->localAddress << ":" << info->localPort << '\n'
+ << "remote addr = " << info->remoteAddress << ":" << info->remotePort;
+ }
+ else
+ {
+ trace << "trust manager evaluating server:\n"
+ << "subject = " << string(subject) << '\n'
+ << "local addr = " << info->localAddress << ":" << info->localPort << '\n'
+ << "remote addr = " << info->remoteAddress << ":" << info->remotePort;
+ }
+ }
+
+ list<list<DistinguishedName> >::const_iterator p;
+
+ //
+ // Fail if we match anything in the reject set.
+ //
+ for(p = reject.begin(); p != reject.end(); ++p)
+ {
+ if(_traceLevel > 1)
+ {
+ Ice::Trace trace(_communicator->getLogger(), "Security");
+ trace << "trust manager rejecting PDNs:\n";
+ for(list<DistinguishedName>::const_iterator r = p->begin(); r != p->end(); ++r)
+ {
+ if(r != p->begin())
+ {
+ trace << ';';
+ }
+ trace << string(*r);
+ }
+ }
+ if(match(*p, subject))
+ {
+ return false;
+ }
+ }
+
+ //
+ // Succeed if we match anything in the accept set.
+ //
+ for(p = accept.begin(); p != accept.end(); ++p)
+ {
+ if(_traceLevel > 1)
+ {
+ Ice::Trace trace(_communicator->getLogger(), "Security");
+ trace << "trust manager accepting PDNs:\n";
+ for(list<DistinguishedName>::const_iterator r = p->begin(); r != p->end(); ++r)
+ {
+ if(r != p->begin())
+ {
+ trace << ';';
+ }
+ trace << string(*r);
+ }
+ }
+ if(match(*p, subject))
+ {
+ return true;
+ }
+ }
+
+ //
+ // At this point we accept the connection if there are no explicit accept rules.
+ //
+ return accept.empty();
+ }
+
+ return false;
+}
+
+bool
+TrustManager::match(const list< DistinguishedName>& matchSet, const DistinguishedName& subject) const
+{
+ for(list<DistinguishedName>::const_iterator r = matchSet.begin(); r != matchSet.end(); ++r)
+ {
+ if(subject.match(*r))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+TrustManager::parse(const string& value, list<DistinguishedName>& reject, list<DistinguishedName>& accept) const
+{
+ if(!value.empty())
+ {
+ RFC2253::RDNEntrySeq dns = RFC2253::parse(value);
+
+ for(RFC2253::RDNEntrySeq::const_iterator p = dns.begin(); p != dns.end(); ++p)
+ {
+ if(p->negate)
+ {
+ reject.push_back(DistinguishedName(p->rdn));
+ }
+ else
+ {
+ accept.push_back(DistinguishedName(p->rdn));
+ }
+ }
+ }
+}