diff options
Diffstat (limited to 'cpp/src/Glacier2/SessionRouterI.cpp')
-rw-r--r-- | cpp/src/Glacier2/SessionRouterI.cpp | 626 |
1 files changed, 378 insertions, 248 deletions
diff --git a/cpp/src/Glacier2/SessionRouterI.cpp b/cpp/src/Glacier2/SessionRouterI.cpp index 8b1dcf98d1e..4e10b51ebef 100644 --- a/cpp/src/Glacier2/SessionRouterI.cpp +++ b/cpp/src/Glacier2/SessionRouterI.cpp @@ -21,6 +21,9 @@ using namespace std; using namespace Ice; using namespace Glacier2; +namespace Glacier2 +{ + class SessionControlI : public SessionControl { public: @@ -39,8 +42,8 @@ public: private: - SessionRouterIPtr _sessionRouter; - ConnectionPtr _connection; + const SessionRouterIPtr _sessionRouter; + const ConnectionPtr _connection; }; class ClientLocator : public ServantLocator @@ -103,11 +106,100 @@ private: const SessionRouterIPtr _sessionRouter; }; +class UserPasswordAuthorizer : public Authorizer +{ +public: + + UserPasswordAuthorizer(const PermissionsVerifierPrx& verifier, const string& user, const string& password) : + _verifier(verifier), _user(user), _password(password) + { + } + + virtual bool + authorize(string& reason, const Ice::Context& ctx) + { + return _verifier->checkPermissions(_user, _password, reason, ctx); + } + +private: + + const PermissionsVerifierPrx _verifier; + const string _user; + const string _password; +}; + +class SSLPasswordAuthorizer : public Authorizer +{ +public: + + SSLPasswordAuthorizer(const SSLPermissionsVerifierPrx& verifier, const SSLInfo& info) : + _verifier(verifier), _info(info) + { + } + + virtual bool + authorize(string& reason, const Ice::Context& ctx) + { + return _verifier->authorize(_info, reason, ctx); + } + +private: + + const SSLPermissionsVerifierPrx _verifier; + const SSLInfo _info; +}; + +class UserSessionFactory : public SessionFactory +{ +public: + + UserSessionFactory(const SessionManagerPrx& manager, const string& user) : + _manager(manager), _user(user) + { + } + + virtual SessionPrx + create(const SessionControlPrx& control, const Ice::Context& ctx) + { + return _manager->create(_user, control, ctx); + } + +private: + + const SessionManagerPrx _manager; + const string _user; +}; + +class SSLSessionFactory : public SessionFactory +{ +public: + + SSLSessionFactory(const SSLSessionManagerPrx& manager, const SSLInfo& info) : + _manager(manager), _info(info) + { + } + + virtual SessionPrx + create(const SessionControlPrx& control, const Ice::Context& ctx) + { + return _manager->create(_info, control, ctx); + } + +private: + + const SSLSessionManagerPrx _manager; + const SSLInfo _info; +}; + +} + Glacier2::SessionRouterI::SessionRouterI(const ObjectAdapterPtr& clientAdapter, const ObjectAdapterPtr& serverAdapter, const ObjectAdapterPtr& adminAdapter, const PermissionsVerifierPrx& verifier, - const SessionManagerPrx& sessionManager) : + const SessionManagerPrx& sessionManager, + const SSLPermissionsVerifierPrx& sslVerifier, + const SSLSessionManagerPrx& sslSessionManager) : _properties(clientAdapter->getCommunicator()->getProperties()), _logger(clientAdapter->getCommunicator()->getLogger()), _sessionTraceLevel(_properties->getPropertyAsInt("Glacier2.Trace.Session")), @@ -117,6 +209,8 @@ Glacier2::SessionRouterI::SessionRouterI(const ObjectAdapterPtr& clientAdapter, _adminAdapter(adminAdapter), _verifier(verifier), _sessionManager(sessionManager), + _sslVerifier(sslVerifier), + _sslSessionManager(sslSessionManager), _sessionTimeout(IceUtil::Time::seconds(_properties->getPropertyAsInt("Glacier2.SessionTimeout"))), _sessionThread(_sessionTimeout > IceUtil::Time() ? new SessionThread(this, _sessionTimeout) : 0), _routersByConnectionHint(_routersByConnection.end()), @@ -141,8 +235,7 @@ Glacier2::SessionRouterI::SessionRouterI(const ObjectAdapterPtr& clientAdapter, // All other calls on the client object adapter are dispatched to // a router servant based on connection information. // - ServantLocatorPtr clientLocator = new ClientLocator(this); - _clientAdapter->addServantLocator(clientLocator, ""); + _clientAdapter->addServantLocator(new ClientLocator(this), ""); // // If there is a server object adapter, all calls on this adapter @@ -151,8 +244,7 @@ Glacier2::SessionRouterI::SessionRouterI(const ObjectAdapterPtr& clientAdapter, // if(_serverAdapter) { - ServantLocatorPtr serverLocator = new ServerLocator(this); - _serverAdapter->addServantLocator(serverLocator, ""); + _serverAdapter->addServantLocator(new ServerLocator(this), ""); } if(_sessionThread) @@ -258,90 +350,27 @@ Glacier2::SessionRouterI::getCategoryForClient(const Ice::Current& current) cons SessionPrx Glacier2::SessionRouterI::createSession(const std::string& userId, const std::string& password, const Current& current) { + SessionFactoryPtr factory; + if(_sessionManager) { - IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); - - if(_destroy) - { - current.con->close(true); - throw ObjectNotExistException(__FILE__, __LINE__); - } - - // - // Check whether a session already exists for the connection. - // - { - map<ConnectionPtr, RouterIPtr>::iterator p; - if(_routersByConnectionHint != _routersByConnection.end() && - _routersByConnectionHint->first == current.con) - { - p = _routersByConnectionHint; - } - else - { - p = _routersByConnection.find(current.con); - } - - if(p != _routersByConnection.end()) - { - CannotCreateSessionException exc; - exc.reason = "session exists"; - throw exc; - } - } - - // - // If some other thread is currently trying to create a - // session, we wait until this thread is finished. - // - bool searchAgain = false; - while(_pending.find(current.con) != _pending.end()) - { - wait(); - - if(_destroy) - { - current.con->close(true); - throw ObjectNotExistException(__FILE__, __LINE__); - } - - searchAgain = true; - } - - // - // Check for existing sessions again if we waited above, as - // new sessions have been added in the meantime. - // - if(searchAgain) - { - map<ConnectionPtr, RouterIPtr>::iterator p; - if(_routersByConnectionHint != _routersByConnection.end() && - _routersByConnectionHint->first == current.con) - { - p = _routersByConnectionHint; - } - else - { - p = _routersByConnection.find(current.con); - } - - if(p != _routersByConnection.end()) - { - CannotCreateSessionException exc; - exc.reason = "session exists"; - throw exc; - } - } + factory = new UserSessionFactory(_sessionManager, userId); + } + return createSessionInternal(userId, true, new UserPasswordAuthorizer(_verifier, userId, password), factory, + current); +} - // - // No session exists yet, so we will try to create one. To - // avoid that other threads try to create sessions for the - // same connection, we add our endpoints to _pending. - // - _pending.insert(current.con); +SessionPrx +Glacier2::SessionRouterI::createSessionFromSecureConnection(const Current& current) +{ + if(!_sslVerifier) + { + PermissionDeniedException exc; + exc.reason = "no configured ssl permissions verifier"; + throw exc; } - Ice::Context ctx = current.ctx; + string userDN; + SSLInfo sslinfo; // // Populate the SSL context information. @@ -349,183 +378,44 @@ Glacier2::SessionRouterI::createSession(const std::string& userId, const std::st try { IceSSL::ConnectionInfo info = IceSSL::getConnectionInfo(current.con); - ctx["SSL.Active"] = "1"; - ctx["SSL.Cipher"] = info.cipher; - ostringstream os; - os << ntohs(info.remoteAddr.sin_port); - ctx["SSL.Remote.Port"] = os.str(); - ctx["SSL.Remote.Host"] = IceInternal::inetAddrToString(info.remoteAddr.sin_addr); - os.str(""); - os << ntohs(info.localAddr.sin_port); - ctx["SSL.Local.Port"] = os.str(); - ctx["SSL.Local.Host"] = IceInternal::inetAddrToString(info.localAddr.sin_addr); - if(!info.certs.empty()) - { - try - { - ctx["SSL.PeerCert"] = info.certs[0]->encode(); - } - catch(const IceSSL::CertificateEncodingException&) - { - } - } - } - catch(const IceSSL::ConnectionInvalidException&) - { - } + sslinfo.remotePort = ntohs(info.remoteAddr.sin_port); + sslinfo.remoteHost = IceInternal::inetAddrToString(info.remoteAddr.sin_addr); + sslinfo.localPort = ntohs(info.localAddr.sin_port); + sslinfo.localHost = IceInternal::inetAddrToString(info.localAddr.sin_addr); - try - { - // - // Check the user-id and password. - // - string reason; - bool ok; + sslinfo.cipher = info.cipher; - try - { - ok = _verifier->checkPermissions(userId, password, reason, ctx); - } - catch(const Exception& ex) + if(info.certs.size() > 0) { - if(_sessionTraceLevel >= 1) + sslinfo.certs.resize(info.certs.size()); + for(unsigned int i = 0; i < info.certs.size(); ++i) { - Trace out(_logger, "Glacier2"); - out << "exception while verifying password\n" << ex; + sslinfo.certs[i] = info.certs[i]->encode(); } - - PermissionDeniedException exc; - exc.reason = "internal server error"; - throw exc; - } - - if(!ok) - { - PermissionDeniedException exc; - exc.reason = reason; - throw exc; + userDN = info.certs[0]->getSubjectDN(); } } - catch(const Exception& ex) - { - IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); - - // - // Signal other threads that we are done with trying to - // establish a session for our connection; - // - _pending.erase(current.con); - notify(); - - ex.ice_throw(); - } - - - SessionPrx session; - Identity controlId; - RouterIPtr router; - - try + catch(const IceSSL::ConnectionInvalidException&) { - // - // If we have a session manager configured, we create a - // client-visible session object. - // - if(_sessionManager) - { - SessionControlPrx control; - if(_adminAdapter) - { - control = SessionControlPrx::uncheckedCast( - _adminAdapter->addWithUUID(new SessionControlI(this, current.con))); - controlId = control->ice_getIdentity(); - } - session = _sessionManager->create(userId, control, ctx); - } - - // - // Add a new per-client router. - // - router = new RouterI(_clientAdapter, _serverAdapter, _adminAdapter, current.con, userId, session, controlId); + PermissionDeniedException exc; + exc.reason = "not ssl connection"; + throw exc; } - catch(const Exception& ex) + catch(const IceSSL::CertificateEncodingException&) { - IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); - - // - // Signal other threads that we are done with trying to - // establish a session for our connection; - // - _pending.erase(current.con); - notify(); - - assert(!router); - - if(session) - { - try - { - session->destroy(); - } - catch(const Exception&) - { - // Ignore all exceptions here. - } - } - - ex.ice_throw(); + PermissionDeniedException exc; + exc.reason = "certificate encoding exception"; + throw exc; } + SessionFactoryPtr factory; + if(_sslSessionManager) { - IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); - - // - // Signal other threads that we are done with trying to - // establish a session for our connection; - // - _pending.erase(current.con); - notify(); - - if(_destroy) - { - try - { - router->destroy(); - } - catch(const Exception&) - { - // Ignore all exceptions here. - } - - current.con->close(true); - throw ObjectNotExistException(__FILE__, __LINE__); - } - - _routersByConnectionHint = _routersByConnection.insert( - _routersByConnectionHint, pair<const ConnectionPtr, RouterIPtr>(current.con, router)); - - if(_serverAdapter) - { - string category = router->getServerProxy(current)->ice_getIdentity().category; - assert(!category.empty()); - pair<map<string, RouterIPtr>::iterator, bool> rc = - _routersByCategory.insert(pair<const string, RouterIPtr>(category, router)); - assert(rc.second); - _routersByCategoryHint = rc.first; - } - - if(_sessionTraceLevel >= 1) - { - Trace out(_logger, "Glacier2"); - out << "created session\n"; - out << router->toString(); - } + factory = new SSLSessionFactory(_sslSessionManager, sslinfo); } - - return session; + return createSessionInternal(userDN, false, new SSLPasswordAuthorizer(_sslVerifier, sslinfo), factory, current); } - void Glacier2::SessionRouterI::destroySession(const Current& current) { @@ -749,6 +639,246 @@ Glacier2::SessionRouterI::expireSessions() } } +SessionPrx +Glacier2::SessionRouterI::createSessionInternal(const string& userId, bool allowAddUserMode, + const AuthorizerPtr& authorizer, const SessionFactoryPtr& factory, + const Current& current) +{ + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + if(_destroy) + { + current.con->close(true); + throw ObjectNotExistException(__FILE__, __LINE__); + } + + // + // Check whether a session already exists for the connection. + // + { + map<ConnectionPtr, RouterIPtr>::iterator p; + if(_routersByConnectionHint != _routersByConnection.end() && + _routersByConnectionHint->first == current.con) + { + p = _routersByConnectionHint; + } + else + { + p = _routersByConnection.find(current.con); + } + + if(p != _routersByConnection.end()) + { + CannotCreateSessionException exc; + exc.reason = "session exists"; + throw exc; + } + } + + // + // If some other thread is currently trying to create a + // session, we wait until this thread is finished. + // + bool searchAgain = false; + while(_pending.find(current.con) != _pending.end()) + { + wait(); + + if(_destroy) + { + current.con->close(true); + throw ObjectNotExistException(__FILE__, __LINE__); + } + + searchAgain = true; + } + + // + // Check for existing sessions again if we waited above, as + // new sessions have been added in the meantime. + // + if(searchAgain) + { + map<ConnectionPtr, RouterIPtr>::iterator p; + if(_routersByConnectionHint != _routersByConnection.end() && + _routersByConnectionHint->first == current.con) + { + p = _routersByConnectionHint; + } + else + { + p = _routersByConnection.find(current.con); + } + + if(p != _routersByConnection.end()) + { + CannotCreateSessionException exc; + exc.reason = "session exists"; + throw exc; + } + } + + // + // No session exists yet, so we will try to create one. To + // avoid that other threads try to create sessions for the + // same connection, we add our endpoints to _pending. + // + _pending.insert(current.con); + } + + try + { + // + // Authorize. + // + string reason; + bool ok; + + try + { + ok = authorizer->authorize(reason, current.ctx); + } + catch(const Exception& ex) + { + if(_sessionTraceLevel >= 1) + { + Trace out(_logger, "Glacier2"); + out << "exception while verifying password\n" << ex; + } + + PermissionDeniedException exc; + exc.reason = "internal server error"; + throw exc; + } + + if(!ok) + { + PermissionDeniedException exc; + exc.reason = reason; + throw exc; + } + } + catch(const Exception& ex) + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + // + // Signal other threads that we are done with trying to + // establish a session for our connection; + // + _pending.erase(current.con); + notify(); + + ex.ice_throw(); + } + + + SessionPrx session; + Identity controlId; + RouterIPtr router; + + try + { + // + // If we have a session manager configured, we create a + // client-visible session object. + // + if(factory) + { + SessionControlPrx control; + if(_adminAdapter) + { + control = SessionControlPrx::uncheckedCast( + _adminAdapter->addWithUUID(new SessionControlI(this, current.con))); + controlId = control->ice_getIdentity(); + } + session = factory->create(control, current.ctx); + } + + // + // Add a new per-client router. + // + router = new RouterI(_clientAdapter, _serverAdapter, _adminAdapter, current.con, userId, allowAddUserMode, + session, controlId); + } + catch(const Exception& ex) + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + // + // Signal other threads that we are done with trying to + // establish a session for our connection; + // + _pending.erase(current.con); + notify(); + + assert(!router); + + if(session) + { + try + { + session->destroy(); + } + catch(const Exception&) + { + // Ignore all exceptions here. + } + } + + ex.ice_throw(); + } + + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + // + // Signal other threads that we are done with trying to + // establish a session for our connection; + // + _pending.erase(current.con); + notify(); + + if(_destroy) + { + try + { + router->destroy(); + } + catch(const Exception&) + { + // Ignore all exceptions here. + } + + current.con->close(true); + throw ObjectNotExistException(__FILE__, __LINE__); + } + + _routersByConnectionHint = _routersByConnection.insert( + _routersByConnectionHint, pair<const ConnectionPtr, RouterIPtr>(current.con, router)); + + if(_serverAdapter) + { + string category = router->getServerProxy(current)->ice_getIdentity().category; + assert(!category.empty()); + pair<map<string, RouterIPtr>::iterator, bool> rc = + _routersByCategory.insert(pair<const string, RouterIPtr>(category, router)); + assert(rc.second); + _routersByCategoryHint = rc.first; + } + + if(_sessionTraceLevel >= 1) + { + Trace out(_logger, "Glacier2"); + out << "created session\n"; + out << router->toString(); + } + } + + return session; +} + Glacier2::SessionRouterI::SessionThread::SessionThread(const SessionRouterIPtr& sessionRouter, const IceUtil::Time& sessionTimeout) : _sessionRouter(sessionRouter), |