You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
356 lines
9.6 KiB
356 lines
9.6 KiB
/*
|
|
* protocol.h - XMPP-Core protocol state machine
|
|
* Copyright (C) 2004 Justin Karneges
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#ifndef PROTOCOL_H
|
|
#define PROTOCOL_H
|
|
|
|
#include <tqpair.h>
|
|
#include "xmlprotocol.h"
|
|
#include "xmpp.h"
|
|
|
|
#define NS_ETHERX "http://etherx.jabber.org/streams"
|
|
#define NS_CLIENT "jabber:client"
|
|
#define NS_SERVER "jabber:server"
|
|
#define NS_DIALBACK "jabber:server:dialback"
|
|
#define NS_STREAMS "urn:ietf:params:xml:ns:xmpp-streams"
|
|
#define NS_TLS "urn:ietf:params:xml:ns:xmpp-tls"
|
|
#define NS_SASL "urn:ietf:params:xml:ns:xmpp-sasl"
|
|
#define NS_SESSION "urn:ietf:params:xml:ns:xmpp-session"
|
|
#define NS_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas"
|
|
#define NS_BIND "urn:ietf:params:xml:ns:xmpp-bind"
|
|
#define NS_XHTML_IM "http://jabber.org/protocol/xhtml-im"
|
|
#define NS_XHTML "http://www.w3.org/1999/xhtml"
|
|
#define NS_CHATSTATES "http://jabber.org/protocol/chatstates"
|
|
|
|
namespace XMPP
|
|
{
|
|
class Version
|
|
{
|
|
public:
|
|
Version(int maj=0, int min=0);
|
|
|
|
int major, minor;
|
|
};
|
|
|
|
class StreamFeatures
|
|
{
|
|
public:
|
|
StreamFeatures();
|
|
|
|
bool tls_supported, sasl_supported, bind_supported;
|
|
bool tls_required;
|
|
TQStringList sasl_mechs;
|
|
};
|
|
|
|
class BasicProtocol : public XmlProtocol
|
|
{
|
|
public:
|
|
// xmpp 1.0 error conditions
|
|
enum SASLCond {
|
|
Aborted,
|
|
IncorrectEncoding,
|
|
InvalidAuthzid,
|
|
InvalidMech,
|
|
MechTooWeak,
|
|
NotAuthorized,
|
|
TemporaryAuthFailure
|
|
};
|
|
enum StreamCond {
|
|
BadFormat,
|
|
BadNamespacePrefix,
|
|
Conflict,
|
|
ConnectionTimeout,
|
|
HostGone,
|
|
HostUnknown,
|
|
ImproperAddressing,
|
|
InternalServerError,
|
|
InvalidFrom,
|
|
InvalidId,
|
|
InvalidNamespace,
|
|
InvalidXml,
|
|
StreamNotAuthorized,
|
|
PolicyViolation,
|
|
RemoteConnectionFailed,
|
|
ResourceConstraint,
|
|
RestrictedXml,
|
|
SeeOtherHost,
|
|
SystemShutdown,
|
|
UndefinedCondition,
|
|
UnsupportedEncoding,
|
|
UnsupportedStanzaType,
|
|
UnsupportedVersion,
|
|
XmlNotWellFormed
|
|
};
|
|
enum BindCond {
|
|
BindBadRequest,
|
|
BindNotAllowed,
|
|
BindConflict
|
|
};
|
|
|
|
// extend the XmlProtocol enums
|
|
enum Need {
|
|
NSASLMechs = XmlProtocol::NCustom, // need SASL mechlist
|
|
NStartTLS, // need to switch on TLS layer
|
|
NSASLFirst, // need SASL first step
|
|
NSASLNext, // need SASL next step
|
|
NSASLLayer, // need to switch on SASL layer
|
|
NCustom = XmlProtocol::NCustom+10
|
|
};
|
|
enum Event {
|
|
EFeatures = XmlProtocol::ECustom, // breakpoint after features packet is received
|
|
ESASLSuccess, // breakpoint after successful sasl auth
|
|
EStanzaReady, // a stanza was received
|
|
EStanzaSent, // a stanza was sent
|
|
EReady, // stream is ready for stanza use
|
|
ECustom = XmlProtocol::ECustom+10
|
|
};
|
|
enum Error {
|
|
ErrProtocol = XmlProtocol::ErrCustom, // there was an error in the xmpp-core protocol exchange
|
|
ErrStream, // <stream:error>, see errCond, errText, and errAppSpec for details
|
|
ErrStartTLS, // server refused starttls
|
|
ErrAuth, // authorization error. errCond holds sasl condition (or numeric code for old-protocol)
|
|
ErrBind, // server refused resource bind
|
|
ErrCustom = XmlProtocol::ErrCustom+10
|
|
};
|
|
|
|
BasicProtocol();
|
|
~BasicProtocol();
|
|
|
|
void reset();
|
|
|
|
// for outgoing xml
|
|
TQDomDocument doc;
|
|
|
|
// sasl-related
|
|
TQString saslMech() const;
|
|
TQByteArray saslStep() const;
|
|
void setSASLMechList(const TQStringList &list);
|
|
void setSASLFirst(const TQString &mech, const TQByteArray &step);
|
|
void setSASLNext(const TQByteArray &step);
|
|
void setSASLAuthed();
|
|
|
|
// send / recv
|
|
void sendStanza(const TQDomElement &e);
|
|
void sendDirect(const TQString &s);
|
|
void sendWhitespace();
|
|
TQDomElement recvStanza();
|
|
|
|
// shutdown
|
|
void shutdown();
|
|
void shutdownWithError(int cond, const TQString &otherHost="");
|
|
|
|
// <stream> information
|
|
TQString to, from, id, lang;
|
|
Version version;
|
|
|
|
// error output
|
|
int errCond;
|
|
TQString errText;
|
|
TQDomElement errAppSpec;
|
|
TQString otherHost;
|
|
|
|
TQByteArray spare; // filled with unprocessed data on NStartTLS and NSASLLayer
|
|
|
|
bool isReady() const;
|
|
|
|
enum { TypeElement, TypeStanza, TypeDirect, TypePing };
|
|
|
|
protected:
|
|
static int stringToSASLCond(const TQString &s);
|
|
static int stringToStreamCond(const TQString &s);
|
|
static TQString saslCondToString(int);
|
|
static TQString streamCondToString(int);
|
|
|
|
void send(const TQDomElement &e, bool clip=false);
|
|
void sendStreamError(int cond, const TQString &text="", const TQDomElement &appSpec=TQDomElement());
|
|
void sendStreamError(const TQString &text); // old-style
|
|
|
|
bool errorAndClose(int cond, const TQString &text="", const TQDomElement &appSpec=TQDomElement());
|
|
bool error(int code);
|
|
void delayErrorAndClose(int cond, const TQString &text="", const TQDomElement &appSpec=TQDomElement());
|
|
void delayError(int code);
|
|
|
|
// reimplemented
|
|
TQDomElement docElement();
|
|
void handleDocOpen(const Parser::Event &pe);
|
|
bool handleError();
|
|
bool handleCloseFinished();
|
|
bool doStep(const TQDomElement &e);
|
|
void itemWritten(int id, int size);
|
|
|
|
virtual TQString defaultNamespace();
|
|
virtual TQStringList extraNamespaces(); // stringlist: prefix,uri,prefix,uri, [...]
|
|
virtual void handleStreamOpen(const Parser::Event &pe);
|
|
virtual bool doStep2(const TQDomElement &e)=0;
|
|
|
|
void setReady(bool b);
|
|
|
|
TQString sasl_mech;
|
|
TQStringList sasl_mechlist;
|
|
TQByteArray sasl_step;
|
|
bool sasl_authed;
|
|
|
|
TQDomElement stanzaToRecv;
|
|
|
|
private:
|
|
struct SASLCondEntry
|
|
{
|
|
const char *str;
|
|
int cond;
|
|
};
|
|
static SASLCondEntry saslCondTable[];
|
|
|
|
struct StreamCondEntry
|
|
{
|
|
const char *str;
|
|
int cond;
|
|
};
|
|
static StreamCondEntry streamCondTable[];
|
|
|
|
struct SendItem
|
|
{
|
|
TQDomElement stanzaToSend;
|
|
TQString stringToSend;
|
|
bool doWhitespace;
|
|
};
|
|
TQValueList<SendItem> sendList;
|
|
|
|
bool doShutdown, delayedError, closeError, ready;
|
|
int stanzasPending, stanzasWritten;
|
|
|
|
void init();
|
|
void extractStreamError(const TQDomElement &e);
|
|
};
|
|
|
|
class CoreProtocol : public BasicProtocol
|
|
{
|
|
public:
|
|
enum {
|
|
NPassword = NCustom, // need password for old-mode
|
|
EDBVerify = ECustom, // breakpoint after db:verify request
|
|
ErrPlain = ErrCustom // server only supports plain, but allowPlain is false locally
|
|
};
|
|
|
|
CoreProtocol();
|
|
~CoreProtocol();
|
|
|
|
void reset();
|
|
|
|
void startClientOut(const Jid &jid, bool oldOnly, bool tlsActive, bool doAuth);
|
|
void startServerOut(const TQString &to);
|
|
void startDialbackOut(const TQString &to, const TQString &from);
|
|
void startDialbackVerifyOut(const TQString &to, const TQString &from, const TQString &id, const TQString &key);
|
|
void startClientIn(const TQString &id);
|
|
void startServerIn(const TQString &id);
|
|
|
|
void setLang(const TQString &s);
|
|
void setAllowTLS(bool b);
|
|
void setAllowBind(bool b);
|
|
void setAllowPlain(bool b); // old-mode
|
|
|
|
void setPassword(const TQString &s);
|
|
void setFrom(const TQString &s);
|
|
void setDialbackKey(const TQString &s);
|
|
|
|
// input
|
|
TQString user, host;
|
|
|
|
// status
|
|
bool old;
|
|
|
|
StreamFeatures features;
|
|
|
|
//static TQString xmlToString(const TQDomElement &e, bool clip=false);
|
|
|
|
class DBItem
|
|
{
|
|
public:
|
|
enum { ResultRequest, ResultGrant, VerifyRequest, VerifyGrant, Validated };
|
|
int type;
|
|
Jid to, from;
|
|
TQString key, id;
|
|
bool ok;
|
|
};
|
|
|
|
private:
|
|
enum Step {
|
|
Start,
|
|
Done,
|
|
SendFeatures,
|
|
GetRequest,
|
|
HandleTLS,
|
|
GetSASLResponse,
|
|
IncHandleSASLSuccess,
|
|
GetFeatures, // read features packet
|
|
HandleFeatures, // act on features, by initiating tls, sasl, or bind
|
|
GetTLSProceed, // read <proceed/> tls response
|
|
GetSASLFirst, // perform sasl first step using provided data
|
|
GetSASLChallenge, // read server sasl challenge
|
|
GetSASLNext, // perform sasl next step using provided data
|
|
HandleSASLSuccess, // handle what must be done after reporting sasl success
|
|
GetBindResponse, // read bind response
|
|
HandleAuthGet, // send old-protocol auth-get
|
|
GetAuthGetResponse, // read auth-get response
|
|
HandleAuthSet, // send old-protocol auth-set
|
|
GetAuthSetResponse // read auth-set response
|
|
};
|
|
|
|
TQValueList<DBItem> dbrequests, dbpending, dbvalidated;
|
|
|
|
bool server, dialback, dialback_verify;
|
|
int step;
|
|
|
|
bool digest;
|
|
bool tls_started, sasl_started;
|
|
|
|
Jid jid;
|
|
bool oldOnly;
|
|
bool allowPlain;
|
|
bool doTLS, doAuth, doBinding;
|
|
TQString password;
|
|
|
|
TQString dialback_id, dialback_key;
|
|
TQString self_from;
|
|
|
|
void init();
|
|
static int getOldErrorCode(const TQDomElement &e);
|
|
bool loginComplete();
|
|
|
|
bool isValidStanza(const TQDomElement &e) const;
|
|
bool grabPendingItem(const Jid &to, const Jid &from, int type, DBItem *item);
|
|
bool normalStep(const TQDomElement &e);
|
|
bool dialbackStep(const TQDomElement &e);
|
|
|
|
// reimplemented
|
|
bool stepAdvancesParser() const;
|
|
bool stepRequiresElement() const;
|
|
void stringSend(const TQString &s);
|
|
void stringRecv(const TQString &s);
|
|
TQString defaultNamespace();
|
|
TQStringList extraNamespaces();
|
|
void handleStreamOpen(const Parser::Event &pe);
|
|
bool doStep2(const TQDomElement &e);
|
|
void elementSend(const TQDomElement &e);
|
|
void elementRecv(const TQDomElement &e);
|
|
};
|
|
}
|
|
|
|
#endif
|