From 2fe5cfecf1d3cf7877fcb609b603add501db8732 Mon Sep 17 00:00:00 2001 From: Manjeet Dahiya Date: Wed, 21 Oct 2009 08:33:09 +0000 Subject: Fix for Issue 17: Authentication and stream security configuration options --- source/QXmppConfiguration.cpp | 48 +++++++++++++++++++++++++++++++-- source/QXmppConfiguration.h | 44 ++++++++++++++++++++++++++++++ source/QXmppStream.cpp | 63 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 146 insertions(+), 9 deletions(-) (limited to 'source') diff --git a/source/QXmppConfiguration.cpp b/source/QXmppConfiguration.cpp index 4ac43607..d17bc28b 100644 --- a/source/QXmppConfiguration.cpp +++ b/source/QXmppConfiguration.cpp @@ -29,8 +29,12 @@ QXmppConfiguration::QXmppConfiguration() : m_port(5222), m_autoAcceptSubscriptions(true), m_sendIntialPresence(true), m_sendRosterRequest(true), - m_keepAlivePingsInterval(100), m_autoReconnectionEnabled(true), - m_useSASLAuthentication(true) + m_keepAlivePingsInterval(100), + m_autoReconnectionEnabled(true), + m_useSASLAuthentication(true), + m_streamSecurityMode(QXmppConfiguration::TLSEnabled), + m_nonSASLAuthMechanism(QXmppConfiguration::NonSASLDigest), + m_SASLAuthMechanism(QXmppConfiguration::SASLPlain) { } @@ -148,3 +152,43 @@ void QXmppConfiguration::setUseSASLAuthentication(bool useSASL) m_useSASLAuthentication = useSASL; } +/// Returns the specified security mode for the stream. The default value is +/// QXmppConfiguration::TLSEnabled. +/// \return StreamSecurityMode + +QXmppConfiguration::StreamSecurityMode QXmppConfiguration::getStreamSecurityMode() const +{ + return m_streamSecurityMode; +} + +/// Specifies the specified security mode for the stream. The default value is +/// QXmppConfiguration::TLSEnabled. +/// \param mode StreamSecurityMode + +void QXmppConfiguration::setStreamSecurityMode( + QXmppConfiguration::StreamSecurityMode mode) +{ + m_streamSecurityMode = mode; +} + +QXmppConfiguration::NonSASLAuthMechanism QXmppConfiguration::getNonSASLAuthMechanism() const +{ + return m_nonSASLAuthMechanism; +} + +void QXmppConfiguration::setNonSASLAuthMechanism( + QXmppConfiguration::NonSASLAuthMechanism mech) +{ + m_nonSASLAuthMechanism = mech; +} + +QXmppConfiguration::SASLAuthMechanism QXmppConfiguration::getSASLAuthMechanism() const +{ + return m_SASLAuthMechanism; +} + +void QXmppConfiguration::setSASLAuthMechanism( + QXmppConfiguration::SASLAuthMechanism mech) +{ + m_SASLAuthMechanism = mech; +} diff --git a/source/QXmppConfiguration.h b/source/QXmppConfiguration.h index fad1de79..03391a50 100644 --- a/source/QXmppConfiguration.h +++ b/source/QXmppConfiguration.h @@ -30,6 +30,35 @@ class QXmppConfiguration { public: + /// An enumeration for type of the Security Mode that is stream is encrypted or not. + /// The server may or may not have TLS feature. Server may force the encryption. + /// Depending upon all this user can specify following options. + enum StreamSecurityMode + { + TLSEnabled = 0, ///< Default, encryption is used if available + TLSDisabled, ///< No encryption is server allows + TLSRequired ///< Encryption is a must otherwise connection would not + ///< be established + }; + + /// An enumeration for various Non-SASL authentication mechanisms available. + /// The server may or may not allow QXmppConfiguration::Plain mechanism. So + /// specifying the mechanism is just a hint to the library. + enum NonSASLAuthMechanism + { + NonSASLPlain = 0,///< Plain + NonSASLDigest ///< Default, + }; + + /// An enumeration for various SASL authentication mechanisms available. + /// The server may or may not allow any particular mechanism. So depending + /// upon the availability of mechanisms on the server the library will choose + /// a mechanism. + enum SASLAuthMechanism + { + SASLPlain = 0 ///< Default + }; + QXmppConfiguration(); ~QXmppConfiguration(); @@ -59,6 +88,17 @@ public: bool getUseSASLAuthentication() const; void setUseSASLAuthentication(bool); + QXmppConfiguration::StreamSecurityMode getStreamSecurityMode() const; + void setStreamSecurityMode(QXmppConfiguration::StreamSecurityMode mode); + + QXmppConfiguration::NonSASLAuthMechanism QXmppConfiguration:: + getNonSASLAuthMechanism() const; + void setNonSASLAuthMechanism(QXmppConfiguration::NonSASLAuthMechanism); + + QXmppConfiguration::SASLAuthMechanism QXmppConfiguration:: + getSASLAuthMechanism() const; + void setSASLAuthMechanism(QXmppConfiguration::SASLAuthMechanism); + private: QString m_host; int m_port; @@ -81,6 +121,10 @@ private: ///< to be used ///< defualt is true and use SASL ///< false would use NonSASL if available + + StreamSecurityMode m_streamSecurityMode; + NonSASLAuthMechanism m_nonSASLAuthMechanism; + SASLAuthMechanism m_SASLAuthMechanism; }; #endif // QXMPPCONFIGURATION_H diff --git a/source/QXmppStream.cpp b/source/QXmppStream.cpp index cd5a52a9..895072d9 100644 --- a/source/QXmppStream.cpp +++ b/source/QXmppStream.cpp @@ -227,13 +227,42 @@ void QXmppStream::parser(const QByteArray& data) namespaceURI() == ns_sasl; bool useSasl = getConfiguration().getUseSASLAuthentication(); - if(nodeRecv.firstChildElement("starttls"). - namespaceURI() == ns_tls && - nodeRecv.firstChildElement("starttls"). + if(nodeRecv.firstChildElement("starttls").namespaceURI() + == ns_tls && !m_socket.isEncrypted()) + { + if(nodeRecv.firstChildElement("starttls"). firstChildElement().tagName() == "required") + { + // TLS is must from the server side + sendStartTls(); + return; + } + else + { + // TLS is optional from the server side + switch(getConfiguration().getStreamSecurityMode()) + { + case QXmppConfiguration::TLSEnabled: + case QXmppConfiguration::TLSRequired: + sendStartTls(); + return; + case QXmppConfiguration::TLSDisabled: + break; + } + } + } + else if(!m_socket.isEncrypted()) // TLS not supported by server { - sendStartTls(); - return; + if(getConfiguration().getStreamSecurityMode() == + QXmppConfiguration::TLSRequired) + { + // disconnect as the for client TLS is compulsory but + // not available on the server + // + log(QString("Disconnecting as TLS not available at the server")); + disconnect(); + return; + } } if((saslAvailable && nonSaslAvailable && !useSasl) || @@ -403,10 +432,29 @@ void QXmppStream::parser(const QByteArray& data) { if(type == "result") { + bool digest = !nodeRecv.firstChildElement("query"). + firstChildElement("digest").isNull(); + bool plain = !nodeRecv.firstChildElement("query"). + firstChildElement("password").isNull(); bool plainText = false; - if ( nodeRecv.firstChildElement("query"). - firstChildElement("digest").isNull() ) + + if(plain && digest) + { + if(getConfiguration().getNonSASLAuthMechanism() == + QXmppConfiguration::NonSASLDigest) + plainText = false; + else + plainText = true; + } + else if(plain) plainText = true; + else if(digest) + plainText = false; + else + { + //TODO Login error + return; + } sendNonSASLAuth(plainText); } } @@ -502,6 +550,7 @@ void QXmppStream::sendStartStream() void QXmppStream::sendToServer(const QByteArray& packet) { + log("CLIENT: " + packet); m_socket.write( packet ); } -- cgit v1.2.3