Changeset - 828ae9d2cb88
[Not reviewed]
0 7 24
HanzZ - 14 years ago 2011-06-18 23:27:54
hanzz.k@gmail.com
Spectrum has to be compiled with official Swiften master branch, not with my fork
31 files changed with 1510 insertions and 11 deletions:
0 comments (0 inline, 0 general)
backends/libpurple/main.cpp
Show inline comments
 
@@ -656,16 +656,16 @@ static void *notify_user_info(PurpleConnection *gc, const char *who, PurpleNotif
 
		vcardEntry = (PurpleNotifyUserInfoEntry *)(vcardEntries->data);
 
		if (purple_notify_user_info_entry_get_label(vcardEntry) && purple_notify_user_info_entry_get_value(vcardEntry)){
 
			label = purple_notify_user_info_entry_get_label(vcardEntry);
 
			if (label == "Given Name"){
 
			if (label == "Given Name") {
 
				firstName = purple_notify_user_info_entry_get_value(vcardEntry);
 
			}
 
			else if (label == "Family Name"){
 
			else if (label == "Family Name") {
 
				lastName = purple_notify_user_info_entry_get_value(vcardEntry);
 
			}
 
			else if (label=="Nickname"){
 
			else if (label=="Nickname") {
 
				nickname = purple_notify_user_info_entry_get_value(vcardEntry);
 
			}
 
			else if (label=="Full Name"){
 
			else if (label=="Full Name") {
 
				fullName = purple_notify_user_info_entry_get_value(vcardEntry);
 
			}
 
			else {
include/Swiften/Server/Server.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/Server/Server.h"
 

	
 
#include <string>
 
#include <boost/bind.hpp>
 

	
 
#include "Swiften/Base/String.h"
 
#include "Swiften/Base/foreach.h"
 
#include "Swiften/Network/Connection.h"
 
#include "Swiften/Network/ConnectionServer.h"
 
#include "Swiften/Network/ConnectionServerFactory.h"
 
#include "Swiften/Elements/Element.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Network/NetworkFactories.h"
 
#include "Swiften/Session/SessionTracer.h"
 
#include "Swiften/Elements/IQ.h"
 
#include "Swiften/Elements/VCard.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include <string>
 
#include "Swiften/Network/ConnectionServer.h"
 
#include "Swiften/Network/ConnectionFactory.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Queries/IQRouter.h"
 

	
 

	
 
namespace Swift {
 

	
 
Server::Server(
 
		EventLoop* eventLoop,
 
		NetworkFactories* networkFactories,
 
		UserRegistry *userRegistry,
 
		const JID& jid,
 
		int port) :
 
			userRegistry_(userRegistry),
 
			port_(port),
 
			eventLoop(eventLoop),
 
			networkFactories_(networkFactories),
 
			stopping(false),
 
			selfJID(jid),
 
			stanzaChannel_(){
 
	stanzaChannel_ = new ServerStanzaChannel();
 
	iqRouter_ = new IQRouter(stanzaChannel_);
 
	tlsFactory = NULL;
 
}
 

	
 
Server::~Server() {
 
	stop();
 
	delete iqRouter_;
 
	delete stanzaChannel_;
 
}
 

	
 
void Server::start() {
 
	assert(!serverFromClientConnectionServer);
 
	serverFromClientConnectionServer = networkFactories_->getConnectionServerFactory()->createConnectionServer(port_);
 
	serverFromClientConnectionServerSignalConnections.push_back(
 
		serverFromClientConnectionServer->onNewConnection.connect(
 
				boost::bind(&Server::handleNewClientConnection, this, _1)));
 
// 	serverFromClientConnectionServerSignalConnections.push_back(
 
// 		serverFromClientConnectionServer->onStopped.connect(
 
// 				boost::bind(&Server::handleClientConnectionServerStopped, this, _1)));
 

	
 
	serverFromClientConnectionServer->start();
 
}
 

	
 
void Server::stop() {
 
	if (stopping) {
 
		return;
 
	}
 

	
 
	stopping = true;
 

	
 
	foreach(boost::shared_ptr<ServerFromClientSession> session, serverFromClientSessions) {
 
		session->finishSession();
 
	}
 
	serverFromClientSessions.clear();
 

	
 
	if (serverFromClientConnectionServer) {
 
		serverFromClientConnectionServer->stop();
 
		foreach(boost::bsignals::connection& connection, serverFromClientConnectionServerSignalConnections) {
 
			connection.disconnect();
 
		}
 
		serverFromClientConnectionServerSignalConnections.clear();
 
		serverFromClientConnectionServer.reset();
 
	}
 

	
 
	stopping = false;
 
// 	onStopped(e);
 
}
 

	
 
void Server::handleNewClientConnection(boost::shared_ptr<Connection> connection) {
 

	
 
	boost::shared_ptr<ServerFromClientSession> serverFromClientSession = boost::shared_ptr<ServerFromClientSession>(
 
			new ServerFromClientSession(idGenerator.generateID(), connection, 
 
					&payloadParserFactories, &payloadSerializers, userRegistry_));
 
	//serverFromClientSession->setAllowSASLEXTERNAL();
 

	
 
	serverFromClientSession->onSessionStarted.connect(
 
			boost::bind(&Server::handleSessionStarted, this, serverFromClientSession));
 
	serverFromClientSession->onSessionFinished.connect(
 
			boost::bind(&Server::handleSessionFinished, this, 
 
			serverFromClientSession));
 
	serverFromClientSession->onDataRead.connect(boost::bind(&Server::handleDataRead, this, _1));
 
	serverFromClientSession->onDataWritten.connect(boost::bind(&Server::handleDataWritten, this, _1));
 

	
 
	dynamic_cast<ServerStanzaChannel *>(stanzaChannel_)->addSession(serverFromClientSession);
 

	
 
	if (tlsFactory) {
 
		serverFromClientSession->addTLSEncryption(tlsFactory, cert);
 
	}
 

	
 
	serverFromClientSession->startSession();
 

	
 
	serverFromClientSessions.push_back(serverFromClientSession);
 
}
 

	
 
void Server::handleDataRead(const SafeByteArray& data) {
 
	onDataRead(data);
 
}
 

	
 
void Server::handleDataWritten(const SafeByteArray& data) {
 
	onDataWritten(data);
 
}
 

	
 
void Server::handleSessionStarted(boost::shared_ptr<ServerFromClientSession>) {
 
// 	onSelfConnected(true);
 
}
 

	
 
void Server::handleSessionFinished(boost::shared_ptr<ServerFromClientSession> session) {
 
	serverFromClientSessions.erase(std::remove(serverFromClientSessions.begin(), serverFromClientSessions.end(), session), serverFromClientSessions.end());
 
}
 

	
 
void Server::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert) {
 
	tlsFactory = tlsContextFactory;
 
	this->cert = cert;
 
}
 

	
 
}
include/Swiften/Server/Server.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 
#include <boost/optional.hpp>
 
#include <vector>
 

	
 
#include "Swiften/Network/BoostIOServiceThread.h"
 
#include "Swiften/Network/ConnectionServer.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include "Swiften/Server/ServerSession.h"
 
#include "Swiften/Base/IDGenerator.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/JID/JID.h"
 
#include "Swiften/Base/ByteArray.h"
 
#include "Swiften/Entity/Entity.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
 
#include "Swiften/TLS/PKCS12Certificate.h"
 

	
 
namespace Swift {
 
	class ConnectionServer;
 
	class SessionTracer;
 
	class EventLoop;
 
	class NetworkFactories;
 
	class StanzaChannel;
 
	class IQRouter;
 
	class TLSServerContextFactory;
 

	
 
	class Server : public Entity {
 
		public:
 
			Server(EventLoop* eventLoop, NetworkFactories* networkFactories, UserRegistry *userRegistry, const JID& jid, int port);
 
			~Server();
 

	
 
			void start();
 
			void stop();
 

	
 
			int getPort() const {
 
				return port_;
 
			}
 

	
 
			StanzaChannel* getStanzaChannel() const {
 
				return stanzaChannel_;
 
			}
 

	
 
			IQRouter* getIQRouter() const {
 
				return iqRouter_;
 
			}
 

	
 
			boost::signal<void (const SafeByteArray&)> onDataRead;
 
			boost::signal<void (const SafeByteArray&)> onDataWritten;
 

	
 
			void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert);
 

	
 
		private:
 
			void handleNewClientConnection(boost::shared_ptr<Connection> c);
 
			void handleSessionStarted(boost::shared_ptr<ServerFromClientSession>);
 
			void handleSessionFinished(boost::shared_ptr<ServerFromClientSession>);
 
			void handleElementReceived(boost::shared_ptr<Element> element, boost::shared_ptr<ServerFromClientSession> session);
 
			void handleDataRead(const SafeByteArray&);
 
			void handleDataWritten(const SafeByteArray&);
 

	
 
		private:
 
			IDGenerator idGenerator;
 
			FullPayloadParserFactoryCollection payloadParserFactories;
 
			FullPayloadSerializerCollection payloadSerializers;
 
			UserRegistry *userRegistry_;
 
			int port_;
 
			EventLoop* eventLoop;
 
			NetworkFactories* networkFactories_;
 
			bool stopping;
 
			boost::shared_ptr<ConnectionServer> serverFromClientConnectionServer;
 
			std::vector<boost::bsignals::connection> serverFromClientConnectionServerSignalConnections;
 
			std::list<boost::shared_ptr<ServerFromClientSession> > serverFromClientSessions;
 
			JID selfJID;
 
			StanzaChannel *stanzaChannel_;
 
			IQRouter *iqRouter_;
 
			TLSServerContextFactory *tlsFactory;
 
			PKCS12Certificate cert;
 
	};
 
}
include/Swiften/Server/ServerFromClientSession.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Server/ServerFromClientSession.h>
 

	
 
#include <boost/bind.hpp>
 

	
 
#include <Swiften/Elements/ProtocolHeader.h>
 
#include <Swiften/Server/UserRegistry.h>
 
#include <Swiften/Network/Connection.h>
 
#include <Swiften/StreamStack/XMPPLayer.h>
 
#include <Swiften/Elements/StreamFeatures.h>
 
#include <Swiften/Elements/ResourceBind.h>
 
#include <Swiften/Elements/StartSession.h>
 
#include <Swiften/Elements/IQ.h>
 
#include <Swiften/Elements/AuthSuccess.h>
 
#include <Swiften/Elements/AuthFailure.h>
 
#include <Swiften/Elements/AuthRequest.h>
 
#include <Swiften/SASL/PLAINMessage.h>
 
#include <Swiften/StreamStack/StreamStack.h>
 
#include <Swiften/StreamStack/TLSServerLayer.h>
 
#include <Swiften/Elements/StartTLSRequest.h>
 
#include <Swiften/Elements/TLSProceed.h>
 

	
 
namespace Swift {
 

	
 
ServerFromClientSession::ServerFromClientSession(
 
		const std::string& id,
 
		boost::shared_ptr<Connection> connection, 
 
		PayloadParserFactoryCollection* payloadParserFactories, 
 
		PayloadSerializerCollection* payloadSerializers,
 
		UserRegistry* userRegistry) : 
 
			Session(connection, payloadParserFactories, payloadSerializers),
 
			id_(id),
 
			userRegistry_(userRegistry),
 
			authenticated_(false),
 
			initialized(false),
 
			allowSASLEXTERNAL(false),
 
			tlsLayer(0),
 
			tlsConnected(false) {
 
	userRegistry->onPasswordValid.connect(boost::bind(&ServerFromClientSession::handlePasswordValid, this, _1));
 
	userRegistry->onPasswordInvalid.connect(boost::bind(&ServerFromClientSession::handlePasswordInvalid, this, _1));
 
}
 

	
 
ServerFromClientSession::~ServerFromClientSession() {
 
	if (tlsLayer) {
 
		delete tlsLayer;
 
	}
 
}
 

	
 
void ServerFromClientSession::handlePasswordValid(const std::string &user) {
 
	if (user != JID(user_, getLocalJID().getDomain()).toString())
 
		return;
 
	getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
 
	authenticated_ = true;
 
	getXMPPLayer()->resetParser();
 
}
 

	
 
void ServerFromClientSession::handlePasswordInvalid(const std::string &user) {
 
	if (user != JID(user_, getLocalJID().getDomain()).toString() || authenticated_)
 
		return;
 
	getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
 
	finishSession(AuthenticationFailedError);
 
}
 

	
 
void ServerFromClientSession::handleElement(boost::shared_ptr<Element> element) {
 
	if (isInitialized()) {
 
		onElementReceived(element);
 
	}
 
	else {
 
		if (AuthRequest* authRequest = dynamic_cast<AuthRequest*>(element.get())) {
 
			if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) {
 
				if (authRequest->getMechanism() == "EXTERNAL") {
 
						getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
 
						authenticated_ = true;
 
						getXMPPLayer()->resetParser();
 
				}
 
				else {
 
					PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : createSafeByteArray(""));
 
					if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) {
 
						user_ = plainMessage.getAuthenticationID();
 
						// we're waiting for usermanager signal now
 
// 						authenticated_ = true;
 
// 						getXMPPLayer()->resetParser();
 
					}
 
					else {
 
						getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
 
						finishSession(AuthenticationFailedError);
 
					}
 
				}
 
			}
 
			else {
 
				getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
 
				finishSession(NoSupportedAuthMechanismsError);
 
			}
 
		}
 
		else if (dynamic_cast<StartTLSRequest*>(element.get()) != NULL) {
 
			getXMPPLayer()->writeElement(boost::shared_ptr<TLSProceed>(new TLSProceed));
 
			getStreamStack()->addLayer(tlsLayer);
 
			tlsLayer->connect();
 
			getXMPPLayer()->resetParser();
 
		}
 
		else if (IQ* iq = dynamic_cast<IQ*>(element.get())) {
 
			if (boost::shared_ptr<ResourceBind> resourceBind = iq->getPayload<ResourceBind>()) {
 
				setRemoteJID(JID(user_, getLocalJID().getDomain(), resourceBind->getResource()));
 
				boost::shared_ptr<ResourceBind> resultResourceBind(new ResourceBind());
 
				resultResourceBind->setJID(getRemoteJID());
 
				getXMPPLayer()->writeElement(IQ::createResult(JID(), iq->getID(), resultResourceBind));
 
			}
 
			else if (iq->getPayload<StartSession>()) {
 
				getXMPPLayer()->writeElement(IQ::createResult(getRemoteJID(), iq->getID()));
 
				setInitialized();
 
			}
 
		}
 
	}
 
}
 

	
 
void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHeader) {
 
	setLocalJID(JID("", incomingHeader.getTo()));
 
	ProtocolHeader header;
 
	header.setFrom(incomingHeader.getTo());
 
	header.setID(id_);
 
	getXMPPLayer()->writeHeader(header);
 

	
 
	boost::shared_ptr<StreamFeatures> features(new StreamFeatures());
 

	
 
	if (!authenticated_) {
 
		if (tlsLayer && !tlsConnected) {
 
			features->setHasStartTLS();
 
		}
 
		features->addAuthenticationMechanism("PLAIN");
 
		if (allowSASLEXTERNAL) {
 
			features->addAuthenticationMechanism("EXTERNAL");
 
		}
 
	}
 
	else {
 
		features->setHasResourceBind();
 
		features->setHasSession();
 
	}
 
	getXMPPLayer()->writeElement(features);
 
}
 

	
 
void ServerFromClientSession::setInitialized() {
 
	initialized = true;
 
	onSessionStarted();
 
}
 

	
 
void ServerFromClientSession::setAllowSASLEXTERNAL() {
 
	allowSASLEXTERNAL = true;
 
}
 

	
 
void ServerFromClientSession::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert) {
 
	tlsLayer = new TLSServerLayer(tlsContextFactory);
 
	if (!tlsLayer->setServerCertificate(cert)) {
 
// 		std::cout << "error\n";
 
		// TODO:
 
// 		onClosed(boost::shared_ptr<Error>(new Error(Error::InvalidTLSCertificateError)));
 
	}
 
	else {
 
		tlsLayer->onError.connect(boost::bind(&ServerFromClientSession::handleTLSError, this));
 
		tlsLayer->onConnected.connect(boost::bind(&ServerFromClientSession::handleTLSConnected, this));
 
// 		getStreamStack()->addLayer(tlsLayer);
 
// 		tlsLayer->onError.connect(boost::bind(&BasicSessionStream::handleTLSError, this));
 
// 		tlsLayer->onConnected.connect(boost::bind(&BasicSessionStream::handleTLSConnected, this));
 
// 		tlsLayer->connect();
 
	}
 
}
 

	
 
}
include/Swiften/Server/ServerFromClientSession.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 
#include <Swiften/Base/boost_bsignals.h>
 
#include <boost/enable_shared_from_this.hpp>
 

	
 
#include <string>
 
#include <Swiften/Session/Session.h>
 
#include <Swiften/JID/JID.h>
 
#include <Swiften/Network/Connection.h>
 
#include <Swiften/Base/ByteArray.h>
 

	
 
namespace Swift {
 
	class ProtocolHeader;
 
	class Element;
 
	class Stanza;
 
	class PayloadParserFactoryCollection;
 
	class PayloadSerializerCollection;
 
	class StreamStack;
 
	class UserRegistry;
 
	class XMPPLayer;
 
	class ConnectionLayer;
 
	class Connection;
 
	class TLSServerLayer;
 
	class TLSServerContextFactory;
 
	class PKCS12Certificate;
 

	
 
	class ServerFromClientSession : public Session {
 
		public:
 
			ServerFromClientSession(
 
					const std::string& id,
 
					boost::shared_ptr<Connection> connection, 
 
					PayloadParserFactoryCollection* payloadParserFactories, 
 
					PayloadSerializerCollection* payloadSerializers,
 
					UserRegistry* userRegistry);
 
			~ServerFromClientSession();
 

	
 
			boost::signal<void ()> onSessionStarted;
 
			void setAllowSASLEXTERNAL();
 
			const std::string &getUser() {
 
				return user_;
 
			}
 

	
 
			void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert);
 

	
 
		private:
 
			void handleElement(boost::shared_ptr<Element>);
 
			void handleStreamStart(const ProtocolHeader& header);
 
			void handlePasswordValid(const std::string &user);
 
			void handlePasswordInvalid(const std::string &user);
 

	
 
			void setInitialized();
 
			bool isInitialized() const { 
 
				return initialized; 
 
			}
 

	
 
			void handleTLSError() { }
 
			void handleTLSConnected() { tlsConnected = true; }
 

	
 
		private:
 
			std::string id_;
 
			UserRegistry* userRegistry_;
 
			bool authenticated_;
 
			bool initialized;
 
			bool allowSASLEXTERNAL;
 
			std::string user_;
 
			TLSServerLayer* tlsLayer;
 
			bool tlsConnected;
 
	};
 
}
include/Swiften/Server/ServerSession.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Server/ServerSession.h>
 

	
 
namespace Swift {
 

	
 
ServerSession::~ServerSession() {
 
}
 

	
 
}
include/Swiften/Server/ServerSession.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include <Swiften/Elements/Stanza.h>
 

	
 
namespace Swift {
 
	class ServerSession {
 
		public:
 
			virtual ~ServerSession();
 

	
 
			virtual const JID& getJID() const = 0;
 
			virtual int getPriority() const = 0;
 

	
 
			virtual void sendStanza(boost::shared_ptr<Stanza>) = 0;
 
	};
 
}
include/Swiften/Server/ServerStanzaChannel.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Base/Error.h"
 

	
 
#include <boost/bind.hpp>
 

	
 
namespace Swift {
 

	
 
namespace {
 
// 	struct PriorityLessThan {
 
// 		bool operator()(const ServerSession* s1, const ServerSession* s2) const {
 
// 			return s1->getPriority() < s2->getPriority();
 
// 		}
 
// 	};
 

	
 
	struct HasJID {
 
		HasJID(const JID& jid) : jid(jid) {}
 
		bool operator()(const boost::shared_ptr<ServerFromClientSession> session) const {
 
			return session->getRemoteJID().equals(jid, JID::WithResource);
 
		}
 
		JID jid;
 
	};
 
}
 

	
 
void ServerStanzaChannel::addSession(boost::shared_ptr<ServerFromClientSession> session) {
 
	sessions.push_back(session);
 
	session->onSessionFinished.connect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
 
	session->onElementReceived.connect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
 
}
 

	
 
void ServerStanzaChannel::removeSession(boost::shared_ptr<ServerFromClientSession> session) {
 
	session->onSessionFinished.disconnect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
 
	session->onElementReceived.disconnect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
 
	sessions.erase(std::remove(sessions.begin(), sessions.end(), session), sessions.end());
 
}
 

	
 
void ServerStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) {
 
	send(iq);
 
}
 

	
 
void ServerStanzaChannel::sendMessage(boost::shared_ptr<Message> message) {
 
	send(message);
 
}
 

	
 
void ServerStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) {
 
	send(presence);
 
}
 

	
 
void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr<Element> element) {
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions.begin(); i != sessions.end(); ++i) {
 
		if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) {
 
			(*i)->sendElement(element);
 
			candidateSessions.push_back(*i);
 
		}
 
	}
 

	
 
	for (std::vector<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = candidateSessions.begin(); i != candidateSessions.end(); ++i) {
 
		(*i)->finishSession();
 
	}
 
}
 

	
 
std::string ServerStanzaChannel::getNewIQID() {
 
	return idGenerator.generateID();
 
}
 

	
 
void ServerStanzaChannel::send(boost::shared_ptr<Stanza> stanza) {
 
	JID to = stanza->getTo();
 
	assert(to.isValid());
 

	
 
	// For a full JID, first try to route to a session with the full JID
 
	if (!to.isBare()) {
 
		std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = std::find_if(sessions.begin(), sessions.end(), HasJID(to));
 
		if (i != sessions.end()) {
 
			(*i)->sendElement(stanza);
 
			return;
 
		}
 
	}
 

	
 
	// Look for candidate sessions
 
	to = to.toBare();
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions.begin(); i != sessions.end(); ++i) {
 
		if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) {
 
			candidateSessions.push_back(*i);
 
			(*i)->sendElement(stanza);
 
		}
 
	}
 
	if (candidateSessions.empty()) {
 
		return;
 
	}
 

	
 
	// Find the session with the highest priority
 
// 	std::vector<ServerSession*>::const_iterator i = std::max_element(sessions.begin(), sessions.end(), PriorityLessThan());
 
// 	(*i)->sendStanza(stanza);
 
	return;
 
}
 

	
 
void ServerStanzaChannel::handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession>& session) {
 
	removeSession(session);
 

	
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
	presence->setFrom(JID(session->getUser(), session->getLocalJID().getDomain()).toString());
 
	presence->setType(Swift::Presence::Unavailable);
 
	onPresenceReceived(presence);
 
}
 

	
 
void ServerStanzaChannel::handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession>& session) {
 
	boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
 
	if (!stanza) {
 
		return;
 
	}
 

	
 
	if (stanza->getFrom().toString().empty()) {
 
		stanza->setFrom(session->getRemoteJID());
 
	}
 

	
 
	if (!stanza->getFrom().isValid())
 
		return;
 
	
 

	
 
	boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza);
 
	if (message) {
 
		onMessageReceived(message);
 
		return;
 
	}
 

	
 
	boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza);
 
	if (presence) {
 
		onPresenceReceived(presence);
 
		return;
 
	}
 

	
 
	boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(stanza);
 
	if (iq) {
 
		onIQReceived(iq);
 
		return;
 
	}
 
}
 

	
 
void ServerStanzaChannel::handleSessionInitialized() {
 
	onAvailableChanged(true);
 
}
 

	
 
}
include/Swiften/Server/ServerStanzaChannel.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include "Swiften/Base/IDGenerator.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Client/StanzaChannel.h"
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/IQ.h"
 
#include "Swiften/Elements/Presence.h"
 

	
 
namespace Swift {
 
	class Error;
 
	class ServerStanzaChannel : public StanzaChannel {
 
		public:
 
			void addSession(boost::shared_ptr<ServerFromClientSession> session);
 
			void removeSession(boost::shared_ptr<ServerFromClientSession> session);
 

	
 
			void sendIQ(boost::shared_ptr<IQ> iq);
 
			void sendMessage(boost::shared_ptr<Message> message);
 
			void sendPresence(boost::shared_ptr<Presence> presence);
 

	
 
			void finishSession(const JID& to, boost::shared_ptr<Element> element);
 

	
 
			bool getStreamManagementEnabled() const {
 
				return false;
 
			}
 

	
 
			bool isAvailable() const {
 
				return true;
 
			}
 

	
 
		private:
 
			std::string getNewIQID();
 
			void send(boost::shared_ptr<Stanza> stanza);
 
			void handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleSessionInitialized();
 

	
 
		private:
 
			IDGenerator idGenerator;
 
			std::list<boost::shared_ptr<ServerFromClientSession> > sessions;
 
	};
 

	
 
}
include/Swiften/Server/ServerStanzaRouter.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Server/ServerStanzaRouter.h>
 
#include <Swiften/Server/ServerSession.h>
 
#include <Swiften/Base/Algorithm.h>
 

	
 
#include <cassert>
 
#include <algorithm>
 

	
 
namespace Swift {
 

	
 
namespace {
 
	struct PriorityLessThan {
 
		bool operator()(const ServerSession* s1, const ServerSession* s2) const {
 
			return s1->getPriority() < s2->getPriority();
 
		}
 
	};
 

	
 
	struct HasJID {
 
		HasJID(const JID& jid) : jid(jid) {}
 
		bool operator()(const ServerSession* session) const {
 
			return session->getJID().equals(jid, JID::WithResource);
 
		}
 
		JID jid;
 
	};
 
}
 

	
 
ServerStanzaRouter::ServerStanzaRouter() {
 
}
 

	
 
bool ServerStanzaRouter::routeStanza(boost::shared_ptr<Stanza> stanza) {
 
	JID to = stanza->getTo();
 
	assert(to.isValid());
 

	
 
	// For a full JID, first try to route to a session with the full JID
 
	if (!to.isBare()) {
 
		std::vector<ServerSession*>::const_iterator i = std::find_if(clientSessions_.begin(), clientSessions_.end(), HasJID(to));
 
		if (i != clientSessions_.end()) {
 
			(*i)->sendStanza(stanza);
 
			return true;
 
		}
 
	}
 

	
 
	// Look for candidate sessions
 
	to = to.toBare();
 
	std::vector<ServerSession*> candidateSessions;
 
	for (std::vector<ServerSession*>::const_iterator i = clientSessions_.begin(); i != clientSessions_.end(); ++i) {
 
		if ((*i)->getJID().equals(to, JID::WithoutResource) && (*i)->getPriority() >= 0) {
 
			candidateSessions.push_back(*i);
 
		}
 
	}
 
	if (candidateSessions.empty()) {
 
		return false;
 
	}
 

	
 
	// Find the session with the highest priority
 
	std::vector<ServerSession*>::const_iterator i = std::max_element(clientSessions_.begin(), clientSessions_.end(), PriorityLessThan());
 
	(*i)->sendStanza(stanza);
 
	return true;
 
}
 

	
 
void ServerStanzaRouter::addClientSession(ServerSession* clientSession) {
 
	clientSessions_.push_back(clientSession);
 
}
 

	
 
void ServerStanzaRouter::removeClientSession(ServerSession* clientSession) {
 
	erase(clientSessions_, clientSession);
 
}
 

	
 
}
include/Swiften/Server/ServerStanzaRouter.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 
#include <map>
 

	
 
#include <Swiften/JID/JID.h>
 
#include <Swiften/Elements/Stanza.h>
 

	
 
namespace Swift {
 
	class ServerSession;
 

	
 
	class ServerStanzaRouter {
 
		public:
 
			ServerStanzaRouter();
 

	
 
			bool routeStanza(boost::shared_ptr<Stanza>);
 

	
 
			void addClientSession(ServerSession*);
 
			void removeClientSession(ServerSession*);
 

	
 
		private:
 
			std::vector<ServerSession*> clientSessions_;
 
	};
 
}
include/Swiften/Server/SimpleUserRegistry.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Server/SimpleUserRegistry.h>
 

	
 
namespace Swift {
 

	
 
SimpleUserRegistry::SimpleUserRegistry() {
 
}
 

	
 
bool SimpleUserRegistry::isValidUserPassword(const JID& user, const SafeByteArray& password) const {
 
	std::map<JID,SafeByteArray>::const_iterator i = users.find(user);
 
	return i != users.end() ? i->second == password : false;
 
}
 

	
 
void SimpleUserRegistry::addUser(const JID& user, const std::string& password) {
 
	users.insert(std::make_pair(user, createSafeByteArray(password)));
 
}
 

	
 
}
include/Swiften/Server/SimpleUserRegistry.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <map>
 

	
 
#include <Swiften/JID/JID.h>
 
#include <string>
 
#include <Swiften/Server/UserRegistry.h>
 

	
 
namespace Swift {
 
	
 

	
 
	class SimpleUserRegistry : public UserRegistry {
 
		public:
 
			SimpleUserRegistry();
 

	
 
			virtual bool isValidUserPassword(const JID& user, const SafeByteArray& password) const;
 
			void addUser(const JID& user, const std::string& password);
 

	
 
		private:
 
			std::map<JID, SafeByteArray> users;
 
	};
 
}
include/Swiften/Server/UserRegistry.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Server/UserRegistry.h>
 

	
 
namespace Swift {
 

	
 
UserRegistry::~UserRegistry() {
 
}
 

	
 
}
include/Swiften/Server/UserRegistry.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <Swiften/Base/SafeByteArray.h>
 
#include <boost/signal.hpp>
 

	
 
namespace Swift {
 
	class JID;
 

	
 
	class UserRegistry {
 
		public:
 
			virtual ~UserRegistry();
 

	
 
			virtual bool isValidUserPassword(const JID& user, const SafeByteArray& password) const = 0;
 

	
 
			boost::signal<void (const std::string &user)> onPasswordValid;
 
			boost::signal<void (const std::string &user)> onPasswordInvalid;
 

	
 
	};
 
}
include/Swiften/StreamStack/TLSServerLayer.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/StreamStack/TLSServerLayer.h"
 

	
 
#include <boost/bind.hpp>
 

	
 
#include "Swiften/TLS/TLSServerContextFactory.h"
 
#include "Swiften/TLS/TLSServerContext.h"
 

	
 
namespace Swift {
 

	
 
TLSServerLayer::TLSServerLayer(TLSServerContextFactory* factory) {
 
	context = factory->createTLSServerContext();
 
	context->onDataForNetwork.connect(boost::bind(&TLSServerLayer::writeDataToChildLayer, this, _1));
 
	context->onDataForApplication.connect(boost::bind(&TLSServerLayer::writeDataToParentLayer, this, _1));
 
	context->onConnected.connect(onConnected);
 
	context->onError.connect(onError);
 
}
 

	
 
TLSServerLayer::~TLSServerLayer() {
 
	delete context;
 
}
 

	
 
void TLSServerLayer::connect() {
 
	context->connect();
 
}
 

	
 
void TLSServerLayer::writeData(const SafeByteArray& data) {
 
	context->handleDataFromApplication(data);
 
}
 

	
 
void TLSServerLayer::handleDataRead(const SafeByteArray& data) {
 
	context->handleDataFromNetwork(data);
 
}
 

	
 
bool TLSServerLayer::setServerCertificate(const PKCS12Certificate& certificate) {
 
	return context->setServerCertificate(certificate);
 
}
 

	
 
Certificate::ref TLSServerLayer::getPeerCertificate() const {
 
	return context->getPeerCertificate();
 
}
 

	
 
boost::shared_ptr<CertificateVerificationError> TLSServerLayer::getPeerCertificateVerificationError() const {
 
	return context->getPeerCertificateVerificationError();
 
}
 

	
 
}
include/Swiften/StreamStack/TLSServerLayer.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/Base/boost_bsignals.h"
 

	
 
#include "Swiften/Base/SafeByteArray.h"
 
#include "Swiften/StreamStack/StreamLayer.h"
 
#include "Swiften/TLS/Certificate.h"
 
#include "Swiften/TLS/CertificateVerificationError.h"
 

	
 
namespace Swift {
 
	class TLSServerContext;
 
	class TLSServerContextFactory;
 
	class PKCS12Certificate;
 

	
 
	class TLSServerLayer : public StreamLayer {
 
		public:
 
			TLSServerLayer(TLSServerContextFactory*);
 
			~TLSServerLayer();
 

	
 
			void connect();
 
			bool setServerCertificate(const PKCS12Certificate&);
 

	
 
			Certificate::ref getPeerCertificate() const;
 
			boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const;
 

	
 
			void writeData(const SafeByteArray& data);
 
			void handleDataRead(const SafeByteArray& data);
 

	
 
			TLSServerContext* getContext() const {
 
				return context;
 
			}
 

	
 
		public:
 
			boost::signal<void ()> onError;
 
			boost::signal<void ()> onConnected;
 

	
 
		private:
 
			TLSServerContext* context;
 
	};
 
}
include/Swiften/TLS/OpenSSL/OpenSSLServerContext.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 
#include "Swiften/Base/Platform.h"
 

	
 
#ifdef SWIFTEN_PLATFORM_WINDOWS
 
#include <windows.h>
 
#include <wincrypt.h>
 
#endif
 

	
 
#include <vector>
 
#include <openssl/err.h>
 
#include <openssl/pkcs12.h>
 

	
 

	
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLCertificate.h"
 
#include "Swiften/TLS/PKCS12Certificate.h"
 

	
 
#pragma GCC diagnostic ignored "-Wold-style-cast"
 

	
 
namespace Swift {
 

	
 
static const int MAX_FINISHED_SIZE = 4096;
 
static const int SSL_READ_BUFFERSIZE = 8192;
 

	
 
static void freeX509Stack(STACK_OF(X509)* stack) {
 
	sk_X509_free(stack);
 
}
 

	
 
static int _sx_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
 
	return 1;
 
}
 

	
 
OpenSSLServerContext::OpenSSLServerContext() : state_(Start), context_(0), handle_(0), readBIO_(0), writeBIO_(0) {
 
	ensureLibraryInitialized();
 
	context_ = SSL_CTX_new(TLSv1_server_method());
 
	SSL_CTX_set_verify(context_, SSL_VERIFY_PEER, _sx_ssl_verify_callback);
 

	
 
	// Load system certs
 
#if defined(SWIFTEN_PLATFORM_WINDOWS)
 
	X509_STORE* store = SSL_CTX_get_cert_store(context_);
 
	HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT");
 
	if (systemStore) {
 
		PCCERT_CONTEXT certContext = NULL;
 
		while (true) {
 
			certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext);
 
			if (!certContext) {
 
				break;
 
			}
 
			ByteArray certData(certContext->pbCertEncoded, certContext->cbCertEncoded);
 
			OpenSSLCertificate cert(certData);
 
			if (store && cert.getInternalX509()) {
 
				X509_STORE_add_cert(store, cert.getInternalX509().get());
 
			}
 
		}
 
	}
 
#elif !defined(SWIFTEN_PLATFORM_MACOSX)
 
	SSL_CTX_load_verify_locations(context_, NULL, "/etc/ssl/certs");
 
#endif
 
}
 

	
 
OpenSSLServerContext::~OpenSSLServerContext() {
 
	SSL_free(handle_);
 
	SSL_CTX_free(context_);
 
}
 

	
 
void OpenSSLServerContext::ensureLibraryInitialized() {
 
	static bool isLibraryInitialized = false;
 
	if (!isLibraryInitialized) {
 
		SSL_load_error_strings();
 
		SSL_library_init();
 
		OpenSSL_add_all_algorithms();
 

	
 
		// Disable compression
 
		/*
 
		STACK_OF(SSL_COMP)* compressionMethods = SSL_COMP_get_compression_methods();
 
		sk_SSL_COMP_zero(compressionMethods);*/
 

	
 
		isLibraryInitialized = true;
 
	}
 
}
 

	
 
void OpenSSLServerContext::connect() {
 
	handle_ = SSL_new(context_);
 
	// Ownership of BIOs is ransferred
 
	readBIO_ = BIO_new(BIO_s_mem());
 
	writeBIO_ = BIO_new(BIO_s_mem());
 
	SSL_set_bio(handle_, readBIO_, writeBIO_);
 

	
 
	state_ = Connecting;
 
	doConnect();
 
}
 

	
 
void OpenSSLServerContext::doConnect() {
 
	int connectResult = SSL_accept(handle_);
 
	int error = SSL_get_error(handle_, connectResult);
 
// 	std::cout << "DO CONNECT\n";
 
	switch (error) {
 
		case SSL_ERROR_NONE: {
 
			if (SSL_is_init_finished(handle_)) {
 
// 				std::cout << "FINISHED\n";
 
				state_ = Connected;
 
				//std::cout << x->name << std::endl;
 
				//const char* comp = SSL_get_current_compression(handle_);
 
				//std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl;
 
				onConnected();
 
				ERR_print_errors_fp(stdout);
 
				sendPendingDataToNetwork();
 
			}
 
			break;
 
		}
 
		case SSL_ERROR_WANT_READ:
 
			sendPendingDataToNetwork();
 
			break;
 
		default:
 
			state_ = Error;
 
// 			std::cout << "AAAAAAAA 1 " << error << " " << connectResult <<  "\n";
 
			ERR_print_errors_fp(stdout);
 
			onError();
 
	}
 
}
 

	
 
void OpenSSLServerContext::sendPendingDataToNetwork() {
 
	int size = BIO_pending(writeBIO_);
 
	if (size > 0) {
 
		SafeByteArray data;
 
		data.resize(size);
 
		BIO_read(writeBIO_, vecptr(data), size);
 
		onDataForNetwork(data);
 
	}
 
}
 

	
 
void OpenSSLServerContext::handleDataFromNetwork(const SafeByteArray& data) {
 
	BIO_write(readBIO_, vecptr(data), data.size());
 
// 	std::cout << "handleDataFromNetwork\n";
 
	switch (state_) {
 
		case Connecting:
 
			doConnect();
 
			break;
 
		case Connected:
 
			sendPendingDataToApplication();
 
			break;
 
		case Start: assert(false); break;
 
		case Error: /*assert(false);*/ break;
 
	}
 
}
 

	
 
void OpenSSLServerContext::handleDataFromApplication(const SafeByteArray& data) {
 
// 	std::cout << "SSL_WRITE\n";
 
	if (SSL_write(handle_, vecptr(data), data.size()) >= 0) {
 
		sendPendingDataToNetwork();
 
	}
 
	else {
 
		state_ = Error;
 
// 		std::cout << "AAAAAAAA 2\n";
 
		onError();
 
	}
 
}
 

	
 
void OpenSSLServerContext::sendPendingDataToApplication() {
 
	SafeByteArray data;
 
	data.resize(SSL_READ_BUFFERSIZE);
 
	int ret = SSL_read(handle_, vecptr(data), data.size());
 
	while (ret > 0) {
 
		data.resize(ret);
 
		onDataForApplication(data);
 
		data.resize(SSL_READ_BUFFERSIZE);
 
		ret = SSL_read(handle_, vecptr(data), data.size());
 
	}
 
	if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) {
 
		state_ = Error;
 
// 		std::cout << "AAAAAAAA 3\n";
 
		onError();
 
	}
 
}
 

	
 
bool OpenSSLServerContext::setServerCertificate(const PKCS12Certificate& certificate) {
 
	if (certificate.isNull()) {
 
// 		std::cout << "error 1\n";
 
		return false;
 
	}
 

	
 
	// Create a PKCS12 structure
 
	BIO* bio = BIO_new(BIO_s_mem());
 
	BIO_write(bio, vecptr(certificate.getData()), certificate.getData().size());
 
	boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free);
 
	BIO_free(bio);
 
	if (!pkcs12) {
 
// 		std::cout << "error 2\n";
 
		return false;
 
	}
 

	
 
	// Parse PKCS12
 
	X509 *certPtr = 0;
 
	EVP_PKEY* privateKeyPtr = 0;
 
	STACK_OF(X509)* caCertsPtr = 0;
 
	int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(certificate.getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr);
 
	if (result != 1) { 
 
// 		std::cout << "error 3\n";
 
		return false;
 
	}
 
	boost::shared_ptr<X509> cert(certPtr, X509_free);
 
	boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free);
 
	boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack);
 

	
 
	// Use the key & certificates
 
	if (SSL_CTX_use_certificate(context_, cert.get()) != 1) {
 
// 		std::cout << "error 4\n";
 
		return false;
 
	}
 
	if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) {
 
// 		std::cout << "error 5\n";
 
		return false;
 
	}
 
	return true;
 
}
 

	
 
Certificate::ref OpenSSLServerContext::getPeerCertificate() const {
 
	boost::shared_ptr<X509> x509Cert(SSL_get_peer_certificate(handle_), X509_free);
 
	if (x509Cert) {
 
		return Certificate::ref(new OpenSSLCertificate(x509Cert));
 
	}
 
	else {
 
		return Certificate::ref();
 
	}
 
}
 

	
 
boost::shared_ptr<CertificateVerificationError> OpenSSLServerContext::getPeerCertificateVerificationError() const {
 
	int verifyResult = SSL_get_verify_result(handle_);
 
	if (verifyResult != X509_V_OK) {
 
		return boost::shared_ptr<CertificateVerificationError>(new CertificateVerificationError(getVerificationErrorTypeForResult(verifyResult)));
 
	}
 
	else {
 
		return boost::shared_ptr<CertificateVerificationError>();
 
	}
 
}
 

	
 
ByteArray OpenSSLServerContext::getFinishMessage() const {
 
	ByteArray data;
 
	data.resize(MAX_FINISHED_SIZE);
 
	size_t size = SSL_get_finished(handle_, vecptr(data), data.size());
 
	data.resize(size);
 
	return data;
 
}
 

	
 
CertificateVerificationError::Type OpenSSLServerContext::getVerificationErrorTypeForResult(int result) {
 
	assert(result != 0);
 
	switch (result) {
 
		case X509_V_ERR_CERT_NOT_YET_VALID:
 
		case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
 
			return CertificateVerificationError::NotYetValid;
 

	
 
		case X509_V_ERR_CERT_HAS_EXPIRED:
 
		case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
 
			return CertificateVerificationError::Expired;
 

	
 
		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
 
		case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
 
			return CertificateVerificationError::SelfSigned;
 

	
 
		case X509_V_ERR_CERT_UNTRUSTED:
 
			return CertificateVerificationError::Untrusted;
 

	
 
		case X509_V_ERR_CERT_REJECTED:
 
			return CertificateVerificationError::Rejected;
 

	
 
		case X509_V_ERR_INVALID_PURPOSE:
 
			return CertificateVerificationError::InvalidPurpose;
 

	
 
		case X509_V_ERR_PATH_LENGTH_EXCEEDED:
 
			return CertificateVerificationError::PathLengthExceeded;
 

	
 
		case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
 
		case X509_V_ERR_CERT_SIGNATURE_FAILURE:
 
		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
 
			return CertificateVerificationError::InvalidSignature;
 

	
 
		case X509_V_ERR_INVALID_CA:
 
		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
 
		case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
 
		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
 
			return CertificateVerificationError::InvalidCA;
 

	
 
		case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
 
		case X509_V_ERR_AKID_SKID_MISMATCH:
 
		case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
 
		case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
 
			return CertificateVerificationError::UnknownError;
 

	
 
		// Unused / should not happen
 
		case X509_V_ERR_CERT_REVOKED:
 
		case X509_V_ERR_OUT_OF_MEM:
 
		case X509_V_ERR_UNABLE_TO_GET_CRL:
 
		case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
 
		case X509_V_ERR_CRL_SIGNATURE_FAILURE:
 
		case X509_V_ERR_CRL_NOT_YET_VALID:
 
		case X509_V_ERR_CRL_HAS_EXPIRED:
 
		case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
 
		case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
 
		case X509_V_ERR_CERT_CHAIN_TOO_LONG:
 
		case X509_V_ERR_APPLICATION_VERIFICATION:
 
		default:
 
			return CertificateVerificationError::UnknownError;
 
	}
 
}
 

	
 
}
include/Swiften/TLS/OpenSSL/OpenSSLServerContext.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <openssl/ssl.h>
 
#include "Swiften/Base/boost_bsignals.h"
 
#include <boost/noncopyable.hpp>
 

	
 
#include "Swiften/TLS/TLSServerContext.h"
 
#include "Swiften/Base/ByteArray.h"
 

	
 
namespace Swift {
 
	class PKCS12Certificate;
 

	
 
	class OpenSSLServerContext : public TLSServerContext, boost::noncopyable {
 
		public:
 
			OpenSSLServerContext();
 
			~OpenSSLServerContext();
 

	
 
			void connect();
 
			bool setServerCertificate(const PKCS12Certificate& cert);
 

	
 
			void handleDataFromNetwork(const SafeByteArray&);
 
			void handleDataFromApplication(const SafeByteArray&);
 

	
 
			Certificate::ref getPeerCertificate() const;
 
			boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const;
 

	
 
			virtual ByteArray getFinishMessage() const;
 

	
 
		private:
 
			static void ensureLibraryInitialized();	
 

	
 
			static CertificateVerificationError::Type getVerificationErrorTypeForResult(int);
 

	
 
			void doConnect();
 
			void sendPendingDataToNetwork();
 
			void sendPendingDataToApplication();
 

	
 
		private:
 
			enum State { Start, Connecting, Connected, Error };
 

	
 
			State state_;
 
			SSL_CTX* context_;
 
			SSL* handle_;
 
			BIO* readBIO_;
 
			BIO* writeBIO_;
 
	};
 
}
include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
 

	
 
namespace Swift {
 

	
 
bool OpenSSLServerContextFactory::canCreate() const {
 
	return true;
 
}
 

	
 
TLSServerContext* OpenSSLServerContextFactory::createTLSServerContext() {
 
	return new OpenSSLServerContext();
 
}
 

	
 
}
include/Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include "Swiften/TLS/TLSServerContextFactory.h"
 

	
 
namespace Swift {
 
	class OpenSSLServerContextFactory : public TLSServerContextFactory {
 
		public:
 
			bool canCreate() const;
 
			virtual TLSServerContext* createTLSServerContext();
 
	};
 
}
include/Swiften/TLS/TLSServerContext.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/TLS/TLSServerContext.h"
 

	
 
namespace Swift {
 

	
 
TLSServerContext::~TLSServerContext() {
 
}
 

	
 
}
include/Swiften/TLS/TLSServerContext.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include "Swiften/Base/boost_bsignals.h"
 
#include <boost/shared_ptr.hpp>
 

	
 
#include "Swiften/Base/SafeByteArray.h"
 
#include "Swiften/TLS/Certificate.h"
 
#include "Swiften/TLS/CertificateVerificationError.h"
 

	
 
namespace Swift {
 
	class PKCS12Certificate;
 

	
 
	class TLSServerContext {
 
		public:
 
			virtual ~TLSServerContext();
 

	
 
			virtual void connect() = 0;
 

	
 
			virtual bool setServerCertificate(const PKCS12Certificate& cert) = 0;
 

	
 
			virtual void handleDataFromNetwork(const SafeByteArray&) = 0;
 
			virtual void handleDataFromApplication(const SafeByteArray&) = 0;
 

	
 
			virtual Certificate::ref getPeerCertificate() const = 0;
 
			virtual CertificateVerificationError::ref getPeerCertificateVerificationError() const = 0;
 

	
 
			virtual ByteArray getFinishMessage() const = 0;
 

	
 
		public:
 
			boost::signal<void (const SafeByteArray&)> onDataForNetwork;
 
			boost::signal<void (const SafeByteArray&)> onDataForApplication;
 
			boost::signal<void ()> onError;
 
			boost::signal<void ()> onConnected;
 
	};
 
}
include/Swiften/TLS/TLSServerContextFactory.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/TLS/TLSServerContextFactory.h"
 

	
 
namespace Swift {
 

	
 
TLSServerContextFactory::~TLSServerContextFactory() {
 
}
 

	
 
}
include/Swiften/TLS/TLSServerContextFactory.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
namespace Swift {
 
	class TLSServerContext;
 

	
 
	class TLSServerContextFactory {
 
		public:
 
			virtual ~TLSServerContextFactory();
 

	
 
			virtual bool canCreate() const = 0;
 

	
 
			virtual TLSServerContext* createTLSServerContext() = 0;
 
	};
 
}
include/transport/networkpluginserver.h
Show inline comments
 
@@ -24,7 +24,7 @@
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Presence/PresenceOracle.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Network/ConnectionServer.h"
 
#include "Swiften/Network/BoostConnectionServer.h"
 
#include "Swiften/Network/Connection.h"
 
#include "storagebackend.h"
 

	
 
@@ -94,7 +94,7 @@ class NetworkPluginServer {
 
		VCardResponder *m_vcardResponder;
 
		RosterResponder *m_rosterResponder;
 
		Config *m_config;
 
		boost::shared_ptr<Swift::ConnectionServer> m_server;
 
		boost::shared_ptr<Swift::BoostConnectionServer> m_server;
 
		std::list<Client *>  m_clients;
 
		Swift::Timer::ref m_pingTimer;
 
		Component *m_component;
include/transport/transport.h
Show inline comments
 
@@ -178,7 +178,6 @@ namespace Transport {
 
			Swift::Component *m_component;
 
			Swift::Server *m_server;
 
			Swift::Timer::ref m_reconnectTimer;
 
			Swift::BoostIOServiceThread m_boostIOServiceThread;
 
			Swift::EntityCapsManager *m_entityCapsManager;
 
			Swift::CapsManager *m_capsManager;
 
			Swift::CapsMemoryStorage *m_capsMemoryStorage;
 
@@ -194,6 +193,7 @@ namespace Transport {
 
			std::string m_protocol;
 
			Swift::JID m_jid;
 
			Factory *m_factory;
 
			Swift::EventLoop *m_loop;
 

	
 
		friend class User;
 
		friend class UserRegistration;
src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp *.h)
 
FILE(GLOB HEADERS ../../include/transport/*.h)
 
FILE(GLOB_RECURSE SWIFTEN_SRC ../include/Swiften/*.cpp)
 
FILE(GLOB HEADERS ../include/transport/*.h)
 
 
if (PROTOBUF_FOUND)
 
	PROTOBUF_GENERATE_CPP(PROTOBUF_SRC PROTOBUF_HDRS "pbnetwork.proto")
 
@@ -8,7 +9,7 @@ endif()
 
 
# SOURCE_GROUP(headers FILES ${HEADERS})
 
 
ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS})
 
ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${SWIFTEN_SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS})
 
ADD_DEFINITIONS(-fPIC)
 
 
TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES})
src/networkpluginserver.cpp
Show inline comments
 
@@ -33,6 +33,7 @@
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "Swiften/Network/BoostConnectionServer.h"
 
#include "pbnetwork.pb.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
@@ -134,7 +135,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 
	m_rosterResponder->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2));
 
	m_rosterResponder->start();
 

	
 
	m_server = component->getNetworkFactories()->getConnectionFactory()->createConnectionServer(boost::lexical_cast<int>(CONFIG_STRING(m_config, "service.backend_port")));
 
	m_server = Swift::BoostConnectionServer::create(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast<int>(CONFIG_STRING(m_config, "service.backend_port")), component->getNetworkFactories()->getIOServiceThread()->getIOService(), component->m_loop);
 
	m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1));
 
	m_server->start();
 

	
src/rostermanager.cpp
Show inline comments
 
@@ -143,7 +143,7 @@ void RosterManager::sendRIE() {
 
		item.setJID(buddy->getJID().toBare());
 
		item.setName(buddy->getAlias());
 
		item.setAction(Swift::RosterItemExchangePayload::Item::Add);
 
		item.setGroups(buddy->getGroups());
 
// 		item.setGroups(buddy->getGroups());
 

	
 
		payload->addItem(item);
 
	}
src/transport.cpp
Show inline comments
 
@@ -60,6 +60,7 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory) {
 
	m_reconnectCount = 0;
 
	m_config = config;
 
	m_factory = factory;
 
	m_loop = loop;
 

	
 
	m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
 

	
0 comments (0 inline, 0 general)