void Session_Service::onAuthentication(const TransportSocket::SocketEventData& data, long requestId, TransportSocketPtr socket, ClientAuthenticatorPtr auth, SignalSubscriberPtr old) { static const std::string cmsig = typeOf<CapabilityMap>()->signature().toString(); boost::recursive_mutex::scoped_lock sl(_requestsMutex); ServiceRequest *sr = serviceRequest(requestId); if (!sr) return; if (data.which() == TransportSocket::Event_Error) { if (old) socket->socketEvent.disconnect(*old); sr->promise.setError(boost::get<std::string>(data)); removeRequest(requestId); return; } #if BOOST_VERSION < 105800 const Message& msg = boost::get<const Message&>(data); #else const Message& msg = boost::relaxed_get<const Message&>(data); #endif int function = msg.function(); bool failure = msg.type() == Message::Type_Error || msg.service() != Message::Service_Server || function != Message::ServerFunction_Authenticate; if (failure) { if (old) socket->socketEvent.disconnect(*old); if (_enforceAuth) { std::stringstream error; if (msg.type() == Message::Type_Error) error << "Error while authenticating: " << msg.value("s", socket).to<std::string>(); else error << "Expected a message for function #" << Message::ServerFunction_Authenticate << " (authentication), received a message for function " << function; sr->promise.setError(error.str()); removeRequest(requestId); } else { session_service_private::sendCapabilities(socket); qi::Future<void> metaObjFut; sr->remoteObject = new qi::RemoteObject(sr->serviceId, socket); metaObjFut = sr->remoteObject->fetchMetaObject(); metaObjFut.connect(&Session_Service::onRemoteObjectComplete, this, _1, requestId); } return; } AnyReference cmref = msg.value(typeOf<CapabilityMap>()->signature(), socket); CapabilityMap authData = cmref.to<CapabilityMap>(); CapabilityMap::iterator authStateIt = authData.find(AuthProvider::State_Key); cmref.destroy(); if (authStateIt == authData.end() || authStateIt->second.to<unsigned int>() < AuthProvider::State_Error || authStateIt->second.to<unsigned int>() > AuthProvider::State_Done) { if (old) socket->socketEvent.disconnect(*old); std::string error = "Invalid authentication state token."; sr->promise.setError(error); removeRequest(requestId); qiLogInfo() << error; return; } if (authData[AuthProvider::State_Key].to<unsigned int>() == AuthProvider::State_Done) { qi::Future<void> metaObjFut; if (old) socket->socketEvent.disconnect(*old); sr->remoteObject = new qi::RemoteObject(sr->serviceId, socket); //ask the remoteObject to fetch the metaObject metaObjFut = sr->remoteObject->fetchMetaObject(); metaObjFut.connect(&Session_Service::onRemoteObjectComplete, this, _1, requestId); return; } CapabilityMap nextData = auth->processAuth(authData); Message authMsg; authMsg.setService(Message::Service_Server); authMsg.setType(Message::Type_Call); authMsg.setValue(nextData, cmsig); authMsg.setFunction(Message::ServerFunction_Authenticate); socket->send(authMsg); }
void Server::onMessageReadyNotAuthenticated(const Message &msg, TransportSocketPtr socket, AuthProviderPtr auth, boost::shared_ptr<bool> first, SignalSubscriberPtr oldSignal) { qiLogVerbose() << "Starting auth message" << msg.address(); int id = msg.id(); int service = msg.service(); int function = msg.action(); int type = msg.type(); Message reply; reply.setId(id); reply.setService(service); if (service != Message::Service_Server || type != Message::Type_Call || function != Message::ServerFunction_Authenticate) { socket->messageReady.disconnect(*oldSignal); if (_enforceAuth) { std::stringstream err; err << "Expected authentication (service #" << Message::Service_Server << ", type #" << Message::Type_Call << ", action #" << Message::ServerFunction_Authenticate << "), received service #" << service << ", type #" << type << ", action #" << function; reply.setType(Message::Type_Error); reply.setError(err.str()); socket->send(reply); socket->disconnect(); qiLogVerbose() << err.str(); } else { server_private::sendCapabilities(socket); qiLogVerbose() << "Authentication is not enforced. Skipping..."; connectMessageReady(socket); onMessageReady(msg, socket); } return; } // the socket now contains the remote capabilities in socket->remoteCapabilities() qiLogVerbose() << "Authenticating client " << socket->remoteEndpoint().str() << "..."; AnyReference cmref = msg.value(typeOf<CapabilityMap>()->signature(), socket); CapabilityMap authData = cmref.to<CapabilityMap>(); cmref.destroy(); CapabilityMap authResult = auth->processAuth(authData); unsigned int state = authResult[AuthProvider::State_Key].to<unsigned int>(); std::string cmsig = typeOf<CapabilityMap>()->signature().toString(); reply.setFunction(function); switch (state) { case AuthProvider::State_Done: qiLogVerbose() << "Client " << socket->remoteEndpoint().str() << " successfully authenticated."; socket->messageReady.disconnect(*oldSignal); connectMessageReady(socket); // no break, we know that authentication is done, send the response to the remote end case AuthProvider::State_Cont: if (*first) { authResult.insert(socket->localCapabilities().begin(), socket->localCapabilities().end()); *first = false; } reply.setValue(authResult, cmsig); reply.setType(Message::Type_Reply); socket->send(reply); break; case AuthProvider::State_Error: default:{ std::stringstream builder; builder << "Authentication failed"; if (authResult.find(AuthProvider::Error_Reason_Key) != authResult.end()) { builder << ": " << authResult[AuthProvider::Error_Reason_Key].to<std::string>(); builder << " [" << _authProviderFactory->authVersionMajor() << "." << _authProviderFactory->authVersionMinor() << "]"; } reply.setType(Message::Type_Error); reply.setError(builder.str()); qiLogVerbose() << builder.str(); socket->send(reply); socket->disconnect(); } } qiLogVerbose() << "Auth ends"; }