From e16866e072f94410321d70daedbcb855ea878cac Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 6 Nov 2011 15:56:40 -0600 Subject: Actually move the kde files that were renamed in the last commit --- kio/misc/kdesasl/CMakeLists.txt | 42 ------ kio/misc/kdesasl/Makefile.am | 12 -- kio/misc/kdesasl/kdesasl.cpp | 285 ---------------------------------------- kio/misc/kdesasl/kdesasl.h | 169 ------------------------ kio/misc/tdesasl/CMakeLists.txt | 42 ++++++ kio/misc/tdesasl/Makefile.am | 12 ++ kio/misc/tdesasl/tdesasl.cpp | 285 ++++++++++++++++++++++++++++++++++++++++ kio/misc/tdesasl/tdesasl.h | 169 ++++++++++++++++++++++++ 8 files changed, 508 insertions(+), 508 deletions(-) delete mode 100644 kio/misc/kdesasl/CMakeLists.txt delete mode 100644 kio/misc/kdesasl/Makefile.am delete mode 100644 kio/misc/kdesasl/kdesasl.cpp delete mode 100644 kio/misc/kdesasl/kdesasl.h create mode 100644 kio/misc/tdesasl/CMakeLists.txt create mode 100644 kio/misc/tdesasl/Makefile.am create mode 100644 kio/misc/tdesasl/tdesasl.cpp create mode 100644 kio/misc/tdesasl/tdesasl.h (limited to 'kio') diff --git a/kio/misc/kdesasl/CMakeLists.txt b/kio/misc/kdesasl/CMakeLists.txt deleted file mode 100644 index 27cacfbb9..000000000 --- a/kio/misc/kdesasl/CMakeLists.txt +++ /dev/null @@ -1,42 +0,0 @@ -################################################# -# -# (C) 2010 Serghei Amelian -# serghei (DOT) amelian (AT) gmail.com -# -# Improvements and feedback are welcome -# -# This file is released under GPL >= 2 -# -################################################# - -include_directories( - ${TQT_INCLUDE_DIRS} - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_BINARY_DIR}/tdecore - ${CMAKE_SOURCE_DIR}/tdecore -) - -link_directories( - ${TQT_LIBRARY_DIRS} -) - - -##### headers ################################### - -install(FILES tdesasl.h DESTINATION ${INCLUDE_INSTALL_DIR}/kio ) - - -##### tdesasl ################################### - -set( target tdesasl ) - -set( ${target}_SRCS - tdesasl.cpp -) - -tde_add_library( ${target} SHARED - SOURCES ${${target}_SRCS} - VERSION 1.2.0 - LINK tdecore-shared - DESTINATION ${LIB_INSTALL_DIR} -) diff --git a/kio/misc/kdesasl/Makefile.am b/kio/misc/kdesasl/Makefile.am deleted file mode 100644 index d308e6770..000000000 --- a/kio/misc/kdesasl/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -INCLUDES=$(all_includes) - -lib_LTLIBRARIES = libtdesasl.la -METASOURCES = AUTO - -tdesaslincludedir = $(includedir)/kio -tdesaslinclude_HEADERS = tdesasl.h - -libtdesasl_la_SOURCES = tdesasl.cpp -libtdesasl_la_LDFLAGS = $(all_libraries) -version-info 3:0:2 -no-undefined -libtdesasl_la_LIBADD = $(LIB_KDECORE) $(LIB_QT) - diff --git a/kio/misc/kdesasl/kdesasl.cpp b/kio/misc/kdesasl/kdesasl.cpp deleted file mode 100644 index 37195faf3..000000000 --- a/kio/misc/kdesasl/kdesasl.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2001-2002 Michael Häckel - $Id$ - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#include "tdesasl.h" - -#include -#include - -#include - -#include -#include - -KDESasl::KDESasl(const KURL &aUrl) -{ - mProtocol = aUrl.protocol(); - mUser = aUrl.user(); - mPass = aUrl.pass(); - mFirst = true; -} - -KDESasl::KDESasl(const TQString &aUser, const TQString &aPass, - const TQString &aProtocol) -{ - mProtocol = aProtocol; - mUser = aUser; - mPass = aPass; - mFirst = true; -} - -KDESasl::~KDESasl() { -} - -TQCString KDESasl::chooseMethod(const TQStrIList aMethods) -{ - if (aMethods.contains("DIGEST-MD5")) mMethod = "DIGEST-MD5"; - else if (aMethods.contains("CRAM-MD5")) mMethod = "CRAM-MD5"; - else if (aMethods.contains("PLAIN")) mMethod = "PLAIN"; - else if (aMethods.contains("LOGIN")) mMethod = "LOGIN"; - else mMethod = TQCString(); - return mMethod; -} - -void KDESasl::setMethod(const TQCString &aMethod) -{ - mMethod = aMethod.upper(); -} - -TQByteArray KDESasl::getPlainResponse() -{ - TQCString user = mUser.utf8(); - TQCString pass = mPass.utf8(); - int userlen = user.length(); - int passlen = pass.length(); - // result = $user\0$user\0$pass (no trailing \0) - TQByteArray result(2 * userlen + passlen + 2); - if ( userlen ) { - memcpy( result.data(), user.data(), userlen ); - memcpy( result.data() + userlen + 1, user.data(), userlen ); - } - if ( passlen ) - memcpy( result.data() + 2 * userlen + 2, pass.data(), passlen ); - result[userlen] = result[2*userlen+1] = '\0'; - return result; -} - -TQByteArray KDESasl::getLoginResponse() -{ - TQByteArray result = (mFirst) ? mUser.utf8() : mPass.utf8(); - mFirst = !mFirst; - if (result.size()) result.resize(result.size() - 1); - return result; -} - -TQByteArray KDESasl::getCramMd5Response(const TQByteArray &aChallenge) -{ - uint i; - TQByteArray secret = mPass.utf8(); - int len = mPass.utf8().length(); - secret.resize(len); - if (secret.size() > 64) - { - KMD5 md5(secret); - secret.duplicate((const char*)(&(md5.rawDigest()[0])), 16); - len = 16; - } - secret.resize(64); - for (i = len; i < 64; i++) secret[i] = 0; - TQByteArray XorOpad(64); - for (i = 0; i < 64; i++) XorOpad[i] = secret[i] ^ 0x5C; - TQByteArray XorIpad(64); - for (i = 0; i < 64; i++) XorIpad[i] = secret[i] ^ 0x36; - KMD5 md5; - md5.update(XorIpad); - md5.update(aChallenge); - KMD5 md5a; - md5a.update(XorOpad); - md5a.update(md5.rawDigest(), 16); - TQByteArray result = mUser.utf8(); - len = mUser.utf8().length(); - result.resize(len + 33); - result[len] = ' '; - TQCString ch = md5a.hexDigest(); - for (i = 0; i < 32; i++) result[i+len+1] = *(ch.data() + i); - return result; -} - -TQByteArray KDESasl::getDigestMd5Response(const TQByteArray &aChallenge) -{ - mFirst = !mFirst; - if (mFirst) return TQByteArray(); - TQCString str, realm, nonce, qop, algorithm, charset; - TQCString nc = "00000001"; - unsigned int a, b, c, d; - a = 0; - while (a < aChallenge.size()) - { - b = a; - while (b < aChallenge.size() && aChallenge[b] != '=') b++; - c = b + 1; - if (aChallenge[c] == '"') - { - d = c + 1; - while (d < aChallenge.size() && aChallenge[d] != '"') d++; - c++; - } else { - d = c; - while (d < aChallenge.size() && aChallenge[d] != ',') d++; - } - str = TQCString(aChallenge.data() + c, d - c + 1); - if (qstrnicmp(aChallenge.data() + a, "realm=", 6) == 0) realm = str; - else if (qstrnicmp(aChallenge.data() + a, "nonce=", 6) == 0) nonce = str; - else if (qstrnicmp(aChallenge.data() + a, "qop=", 4) == 0) qop = str; - else if (qstrnicmp(aChallenge.data() + a, "algorithm=", 10) == 0) - algorithm = str; - else if (qstrnicmp(aChallenge.data() + a, "charset=", 8) == 0) - charset = str; - a = (d < aChallenge.size() && aChallenge[d] == '"') ? d + 2 : d + 1; - } - if (qop.isEmpty()) qop = "auth"; - qop = "auth"; - bool utf8 = qstricmp(charset, "utf-8") == 0; - TQCString digestUri = TQCString(mProtocol.latin1()) + "/" + realm; - - /* Calculate the response */ - /* Code based on code from the http io-slave - Copyright (C) 2000,2001 Dawit Alemayehu - Copyright (C) 2000,2001 Waldo Bastian - Copyright (C) 2000,2001 George Staikos */ - KMD5 md, md2; - TQCString HA1, HA2; - TQCString cnonce; - cnonce.setNum((1 + static_cast(100000.0*rand()/(RAND_MAX+1.0)))); - cnonce = KCodecs::base64Encode( cnonce ); - - // Calculate H(A1) - TQCString authStr = (utf8) ? mUser.utf8() : TQCString(mUser.latin1()); - authStr += ':'; - authStr += realm; - authStr += ':'; - authStr += (utf8) ? mPass.utf8() : TQCString(mPass.latin1()); - - md.update( authStr ); - authStr = ""; - if ( algorithm == "md5-sess" ) - { - authStr += ':'; - authStr += nonce; - authStr += ':'; - authStr += cnonce; - } - md2.reset(); - /* SASL authentication uses rawDigest here, whereas HTTP authentication uses - hexDigest() */ - md2.update(md.rawDigest(), 16); - md2.update( authStr ); - md2.hexDigest( HA1 ); - - // Calcualte H(A2) - authStr = "AUTHENTICATE:"; - authStr += digestUri; - if ( qop == "auth-int" || qop == "auth-conf" ) - { - authStr += ":00000000000000000000000000000000"; - } - md.reset(); - md.update( authStr ); - md.hexDigest( HA2 ); - - // Calcualte the response. - authStr = HA1; - authStr += ':'; - authStr += nonce; - authStr += ':'; - if ( !qop.isEmpty() ) - { - authStr += nc; - authStr += ':'; - authStr += cnonce; - authStr += ':'; - authStr += qop; - authStr += ':'; - } - authStr += HA2; - md.reset(); - md.update( authStr ); - TQCString response = md.hexDigest(); - /* End of response calculation */ - - TQCString result; - if (utf8) - { - result = "charset=utf-8,username=\"" + mUser.utf8(); - } else { - result = "charset=iso-8859-1,username=\"" + TQCString(mUser.latin1()); - } - result += "\",realm=\"" + realm + "\",nonce=\"" + nonce; - result += "\",nc=" + nc + ",cnonce=\"" + cnonce; - result += "\",digest-uri=\"" + digestUri; - result += "\",response=" + response + ",qop=" + qop; - TQByteArray ba; - ba.duplicate(result.data(), result.length()); - return ba; -} - -TQByteArray KDESasl::getBinaryResponse(const TQByteArray &aChallenge, bool aBase64) -{ - if (aBase64) - { - TQByteArray ba; - KCodecs::base64Decode(aChallenge, ba); - KCodecs::base64Encode(getBinaryResponse(ba, false), ba); - return ba; - } - if (qstricmp(mMethod, "PLAIN") == 0) return getPlainResponse(); - if (qstricmp(mMethod, "LOGIN") == 0) return getLoginResponse(); - if (qstricmp(mMethod, "CRAM-MD5") == 0) - return getCramMd5Response(aChallenge); - if (qstricmp(mMethod, "DIGEST-MD5") == 0) - return getDigestMd5Response(aChallenge); -// return getDigestMd5Response(TQCString("realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8")); - return TQByteArray(); -} - -TQCString KDESasl::getResponse(const TQByteArray &aChallenge, bool aBase64) -{ - TQByteArray ba = getBinaryResponse(aChallenge, aBase64); - return TQCString(ba.data(), ba.size() + 1); -} - -TQCString KDESasl::method() const { - return mMethod; -} - -bool KDESasl::clientStarts() const { - return method() == "PLAIN"; -} - -bool KDESasl::dialogComplete( int n ) const { - if ( method() == "PLAIN" || method() == "CRAM-MD5" ) - return n >= 1; - if ( method() == "LOGIN" || method() == "DIGEST-MD5" ) - return n >= 2; - return true; -} - -bool KDESasl::isClearTextMethod() const { - return method() == "PLAIN" || method() == "LOGIN" ; -} diff --git a/kio/misc/kdesasl/kdesasl.h b/kio/misc/kdesasl/kdesasl.h deleted file mode 100644 index 5f0279f34..000000000 --- a/kio/misc/kdesasl/kdesasl.h +++ /dev/null @@ -1,169 +0,0 @@ -/* This file is part of the KDE libraries - Copyright (C) 2001-2002 Michael Häckel - $Id$ - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License version 2 as published by the Free Software Foundation. - - 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this library; see the file COPYING.LIB. If not, write to - the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. -*/ - -#ifndef KDESASL_H -#define KDESASL_H - -#include - -#include - -class KURL; -class TQStrIList; - -/** - * This library can create responses for SASL authentication for a given - * challenge and a given secret. This way of authentication is common for - * SMTP, POP3, IMAP and LDAP. - * - * SASL is one way strong encryption and therefore useful for authentication, - * but not for secret information transfer. - * It is possibly to prove with SASL to know a shared secret like a password. - * It is not possible with SASL to transfer any other information in an - * encrypted way. For that purpose OpenPGP or SSL are useful. - * - * Currently PLAIN (RFC 2595), LOGIN (not really a SASL mechanism, but - * used like that in IMAP and SMTP), CRAM-MD5 (RFC 2195) and - * DIGEST-MD5 (RFC 2831) authentication are supported. PLAIN and - * LOGIN transmit the credentials in the clear (apart from a possible - * base64 encoding). - * - * For KDE 3.2, the API has been extended to allow transparent use of - * all currently supported SASL mechanisms. Example: - * \code - * KDESasl sasl( myUser, myPass, myProtocol ); - * if ( !sasl.chooseMethod( myMechanismsSupportedByServer ) ) - * return false; // couldn't agree on a method - * - * int numResponses = 0; - * if ( sasl.clientStarts() ) { // check whether we're supposed to start the dialog - * ++numResponses; - * mySendAuthCommand( sasl.method(), sasl.getResponse() ); - * } else { - * mySendAuthCommand( sasl.method() ); - * } - * for ( ; !sasl.dialogComplete( numResponses ) ; ++numResponses ) { - * TQByteArray challenge = myRecvChallenge(); - * mySendResponse( sasl.getResponse( challenge ) ); - * } - * return myCheckSuccess(); - * \endcode - * - * @author Michael Häckel - * @version $Id$ - */ - -class KIO_EXPORT KDESasl -{ - -public: - /** - * Construct a sasl object and initialize it with the username and password - * passed via the url. - */ - KDESasl(const KURL &aUrl); - /** - * This is a conveniece function and differs from the above function only by - * what arguments it accepts. - */ - KDESasl(const TQString &aUser, const TQString &aPass, const TQString &aProtocol); - /* - * You need to have a virtual destructor! - */ - virtual ~KDESasl(); - /** - * @returns the most secure method from the given methods and use it for - * further operations. - */ - virtual TQCString chooseMethod(const TQStrIList aMethods); - /** - * Explicitely set the SASL method used. - */ - virtual void setMethod(const TQCString &aMethod); - /** - * @return the SASL method used. - * @since 3.2 - */ - TQCString method() const; - /** - * @param numCalls number of times getResponse() has been called. - * @return whether the challenge/response dialog has completed - * - * @since 3.2 - */ - bool dialogComplete( int numCalls ) const; - /** - * @return whether the currently selected mechanism results in - * cleartext passwords being sent over the network and thus should - * be used only under TLS/SSL cover or for legacy servers. - * - * @since 3.2 - */ - bool isClearTextMethod() const; - /** - * Creates a response using the formerly chosen SASL method. - * For LOGIN authentication you have to call this function twice. KDESasl - * realizes on its own, if you are calling it for the first or for the - * second time. - * @param aChallenge is the challenge sent to create a response for - * @param aBase64 specifies, whether the authentication protocol uses base64 - * encoding. The challenge is decoded from base64 and the response is - * encoded base64 if set to true. - */ - TQCString getResponse(const TQByteArray &aChallenge=TQByteArray(), bool aBase64 = true); - /** - * Create a response as above but place it in a QByteArray - */ - TQByteArray getBinaryResponse(const TQByteArray &aChallenge=TQByteArray(), bool aBase64=true); - /** - * Returns true if the client is supposed to initiate the - * challenge-respinse dialog with an initial response (which most - * protocols can transfer alongside the authentication command as an - * optional second parameter). This method relieves the sasl user - * from knowing details about the mechanism. If true, use - * #getResponse() with a null challenge. - * - * @since 3.2 - */ - bool clientStarts() const; -protected: - /** - * PLAIN authentication as described in RFC 2595 - */ - virtual TQByteArray getPlainResponse(); - /** - * LOGIN authentication - */ - virtual TQByteArray getLoginResponse(); - /** - * CRAM-MD5 authentication as described in RFC 2195 - */ - virtual TQByteArray getCramMd5Response(const TQByteArray &aChallenge); - /** - * DIGEST-MD5 authentication as described in RFC 2831 - */ - virtual TQByteArray getDigestMd5Response(const TQByteArray &aChallenge); - -private: - TQString mProtocol, mUser, mPass; - TQCString mMethod; - bool mFirst; -}; - -#endif diff --git a/kio/misc/tdesasl/CMakeLists.txt b/kio/misc/tdesasl/CMakeLists.txt new file mode 100644 index 000000000..27cacfbb9 --- /dev/null +++ b/kio/misc/tdesasl/CMakeLists.txt @@ -0,0 +1,42 @@ +################################################# +# +# (C) 2010 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${TQT_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/tdecore + ${CMAKE_SOURCE_DIR}/tdecore +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### headers ################################### + +install(FILES tdesasl.h DESTINATION ${INCLUDE_INSTALL_DIR}/kio ) + + +##### tdesasl ################################### + +set( target tdesasl ) + +set( ${target}_SRCS + tdesasl.cpp +) + +tde_add_library( ${target} SHARED + SOURCES ${${target}_SRCS} + VERSION 1.2.0 + LINK tdecore-shared + DESTINATION ${LIB_INSTALL_DIR} +) diff --git a/kio/misc/tdesasl/Makefile.am b/kio/misc/tdesasl/Makefile.am new file mode 100644 index 000000000..d308e6770 --- /dev/null +++ b/kio/misc/tdesasl/Makefile.am @@ -0,0 +1,12 @@ +INCLUDES=$(all_includes) + +lib_LTLIBRARIES = libtdesasl.la +METASOURCES = AUTO + +tdesaslincludedir = $(includedir)/kio +tdesaslinclude_HEADERS = tdesasl.h + +libtdesasl_la_SOURCES = tdesasl.cpp +libtdesasl_la_LDFLAGS = $(all_libraries) -version-info 3:0:2 -no-undefined +libtdesasl_la_LIBADD = $(LIB_KDECORE) $(LIB_QT) + diff --git a/kio/misc/tdesasl/tdesasl.cpp b/kio/misc/tdesasl/tdesasl.cpp new file mode 100644 index 000000000..37195faf3 --- /dev/null +++ b/kio/misc/tdesasl/tdesasl.cpp @@ -0,0 +1,285 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001-2002 Michael Häckel + $Id$ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "tdesasl.h" + +#include +#include + +#include + +#include +#include + +KDESasl::KDESasl(const KURL &aUrl) +{ + mProtocol = aUrl.protocol(); + mUser = aUrl.user(); + mPass = aUrl.pass(); + mFirst = true; +} + +KDESasl::KDESasl(const TQString &aUser, const TQString &aPass, + const TQString &aProtocol) +{ + mProtocol = aProtocol; + mUser = aUser; + mPass = aPass; + mFirst = true; +} + +KDESasl::~KDESasl() { +} + +TQCString KDESasl::chooseMethod(const TQStrIList aMethods) +{ + if (aMethods.contains("DIGEST-MD5")) mMethod = "DIGEST-MD5"; + else if (aMethods.contains("CRAM-MD5")) mMethod = "CRAM-MD5"; + else if (aMethods.contains("PLAIN")) mMethod = "PLAIN"; + else if (aMethods.contains("LOGIN")) mMethod = "LOGIN"; + else mMethod = TQCString(); + return mMethod; +} + +void KDESasl::setMethod(const TQCString &aMethod) +{ + mMethod = aMethod.upper(); +} + +TQByteArray KDESasl::getPlainResponse() +{ + TQCString user = mUser.utf8(); + TQCString pass = mPass.utf8(); + int userlen = user.length(); + int passlen = pass.length(); + // result = $user\0$user\0$pass (no trailing \0) + TQByteArray result(2 * userlen + passlen + 2); + if ( userlen ) { + memcpy( result.data(), user.data(), userlen ); + memcpy( result.data() + userlen + 1, user.data(), userlen ); + } + if ( passlen ) + memcpy( result.data() + 2 * userlen + 2, pass.data(), passlen ); + result[userlen] = result[2*userlen+1] = '\0'; + return result; +} + +TQByteArray KDESasl::getLoginResponse() +{ + TQByteArray result = (mFirst) ? mUser.utf8() : mPass.utf8(); + mFirst = !mFirst; + if (result.size()) result.resize(result.size() - 1); + return result; +} + +TQByteArray KDESasl::getCramMd5Response(const TQByteArray &aChallenge) +{ + uint i; + TQByteArray secret = mPass.utf8(); + int len = mPass.utf8().length(); + secret.resize(len); + if (secret.size() > 64) + { + KMD5 md5(secret); + secret.duplicate((const char*)(&(md5.rawDigest()[0])), 16); + len = 16; + } + secret.resize(64); + for (i = len; i < 64; i++) secret[i] = 0; + TQByteArray XorOpad(64); + for (i = 0; i < 64; i++) XorOpad[i] = secret[i] ^ 0x5C; + TQByteArray XorIpad(64); + for (i = 0; i < 64; i++) XorIpad[i] = secret[i] ^ 0x36; + KMD5 md5; + md5.update(XorIpad); + md5.update(aChallenge); + KMD5 md5a; + md5a.update(XorOpad); + md5a.update(md5.rawDigest(), 16); + TQByteArray result = mUser.utf8(); + len = mUser.utf8().length(); + result.resize(len + 33); + result[len] = ' '; + TQCString ch = md5a.hexDigest(); + for (i = 0; i < 32; i++) result[i+len+1] = *(ch.data() + i); + return result; +} + +TQByteArray KDESasl::getDigestMd5Response(const TQByteArray &aChallenge) +{ + mFirst = !mFirst; + if (mFirst) return TQByteArray(); + TQCString str, realm, nonce, qop, algorithm, charset; + TQCString nc = "00000001"; + unsigned int a, b, c, d; + a = 0; + while (a < aChallenge.size()) + { + b = a; + while (b < aChallenge.size() && aChallenge[b] != '=') b++; + c = b + 1; + if (aChallenge[c] == '"') + { + d = c + 1; + while (d < aChallenge.size() && aChallenge[d] != '"') d++; + c++; + } else { + d = c; + while (d < aChallenge.size() && aChallenge[d] != ',') d++; + } + str = TQCString(aChallenge.data() + c, d - c + 1); + if (qstrnicmp(aChallenge.data() + a, "realm=", 6) == 0) realm = str; + else if (qstrnicmp(aChallenge.data() + a, "nonce=", 6) == 0) nonce = str; + else if (qstrnicmp(aChallenge.data() + a, "qop=", 4) == 0) qop = str; + else if (qstrnicmp(aChallenge.data() + a, "algorithm=", 10) == 0) + algorithm = str; + else if (qstrnicmp(aChallenge.data() + a, "charset=", 8) == 0) + charset = str; + a = (d < aChallenge.size() && aChallenge[d] == '"') ? d + 2 : d + 1; + } + if (qop.isEmpty()) qop = "auth"; + qop = "auth"; + bool utf8 = qstricmp(charset, "utf-8") == 0; + TQCString digestUri = TQCString(mProtocol.latin1()) + "/" + realm; + + /* Calculate the response */ + /* Code based on code from the http io-slave + Copyright (C) 2000,2001 Dawit Alemayehu + Copyright (C) 2000,2001 Waldo Bastian + Copyright (C) 2000,2001 George Staikos */ + KMD5 md, md2; + TQCString HA1, HA2; + TQCString cnonce; + cnonce.setNum((1 + static_cast(100000.0*rand()/(RAND_MAX+1.0)))); + cnonce = KCodecs::base64Encode( cnonce ); + + // Calculate H(A1) + TQCString authStr = (utf8) ? mUser.utf8() : TQCString(mUser.latin1()); + authStr += ':'; + authStr += realm; + authStr += ':'; + authStr += (utf8) ? mPass.utf8() : TQCString(mPass.latin1()); + + md.update( authStr ); + authStr = ""; + if ( algorithm == "md5-sess" ) + { + authStr += ':'; + authStr += nonce; + authStr += ':'; + authStr += cnonce; + } + md2.reset(); + /* SASL authentication uses rawDigest here, whereas HTTP authentication uses + hexDigest() */ + md2.update(md.rawDigest(), 16); + md2.update( authStr ); + md2.hexDigest( HA1 ); + + // Calcualte H(A2) + authStr = "AUTHENTICATE:"; + authStr += digestUri; + if ( qop == "auth-int" || qop == "auth-conf" ) + { + authStr += ":00000000000000000000000000000000"; + } + md.reset(); + md.update( authStr ); + md.hexDigest( HA2 ); + + // Calcualte the response. + authStr = HA1; + authStr += ':'; + authStr += nonce; + authStr += ':'; + if ( !qop.isEmpty() ) + { + authStr += nc; + authStr += ':'; + authStr += cnonce; + authStr += ':'; + authStr += qop; + authStr += ':'; + } + authStr += HA2; + md.reset(); + md.update( authStr ); + TQCString response = md.hexDigest(); + /* End of response calculation */ + + TQCString result; + if (utf8) + { + result = "charset=utf-8,username=\"" + mUser.utf8(); + } else { + result = "charset=iso-8859-1,username=\"" + TQCString(mUser.latin1()); + } + result += "\",realm=\"" + realm + "\",nonce=\"" + nonce; + result += "\",nc=" + nc + ",cnonce=\"" + cnonce; + result += "\",digest-uri=\"" + digestUri; + result += "\",response=" + response + ",qop=" + qop; + TQByteArray ba; + ba.duplicate(result.data(), result.length()); + return ba; +} + +TQByteArray KDESasl::getBinaryResponse(const TQByteArray &aChallenge, bool aBase64) +{ + if (aBase64) + { + TQByteArray ba; + KCodecs::base64Decode(aChallenge, ba); + KCodecs::base64Encode(getBinaryResponse(ba, false), ba); + return ba; + } + if (qstricmp(mMethod, "PLAIN") == 0) return getPlainResponse(); + if (qstricmp(mMethod, "LOGIN") == 0) return getLoginResponse(); + if (qstricmp(mMethod, "CRAM-MD5") == 0) + return getCramMd5Response(aChallenge); + if (qstricmp(mMethod, "DIGEST-MD5") == 0) + return getDigestMd5Response(aChallenge); +// return getDigestMd5Response(TQCString("realm=\"elwood.innosoft.com\",nonce=\"OA6MG9tEQGm2hh\",qop=\"auth\",algorithm=md5-sess,charset=utf-8")); + return TQByteArray(); +} + +TQCString KDESasl::getResponse(const TQByteArray &aChallenge, bool aBase64) +{ + TQByteArray ba = getBinaryResponse(aChallenge, aBase64); + return TQCString(ba.data(), ba.size() + 1); +} + +TQCString KDESasl::method() const { + return mMethod; +} + +bool KDESasl::clientStarts() const { + return method() == "PLAIN"; +} + +bool KDESasl::dialogComplete( int n ) const { + if ( method() == "PLAIN" || method() == "CRAM-MD5" ) + return n >= 1; + if ( method() == "LOGIN" || method() == "DIGEST-MD5" ) + return n >= 2; + return true; +} + +bool KDESasl::isClearTextMethod() const { + return method() == "PLAIN" || method() == "LOGIN" ; +} diff --git a/kio/misc/tdesasl/tdesasl.h b/kio/misc/tdesasl/tdesasl.h new file mode 100644 index 000000000..5f0279f34 --- /dev/null +++ b/kio/misc/tdesasl/tdesasl.h @@ -0,0 +1,169 @@ +/* This file is part of the KDE libraries + Copyright (C) 2001-2002 Michael Häckel + $Id$ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KDESASL_H +#define KDESASL_H + +#include + +#include + +class KURL; +class TQStrIList; + +/** + * This library can create responses for SASL authentication for a given + * challenge and a given secret. This way of authentication is common for + * SMTP, POP3, IMAP and LDAP. + * + * SASL is one way strong encryption and therefore useful for authentication, + * but not for secret information transfer. + * It is possibly to prove with SASL to know a shared secret like a password. + * It is not possible with SASL to transfer any other information in an + * encrypted way. For that purpose OpenPGP or SSL are useful. + * + * Currently PLAIN (RFC 2595), LOGIN (not really a SASL mechanism, but + * used like that in IMAP and SMTP), CRAM-MD5 (RFC 2195) and + * DIGEST-MD5 (RFC 2831) authentication are supported. PLAIN and + * LOGIN transmit the credentials in the clear (apart from a possible + * base64 encoding). + * + * For KDE 3.2, the API has been extended to allow transparent use of + * all currently supported SASL mechanisms. Example: + * \code + * KDESasl sasl( myUser, myPass, myProtocol ); + * if ( !sasl.chooseMethod( myMechanismsSupportedByServer ) ) + * return false; // couldn't agree on a method + * + * int numResponses = 0; + * if ( sasl.clientStarts() ) { // check whether we're supposed to start the dialog + * ++numResponses; + * mySendAuthCommand( sasl.method(), sasl.getResponse() ); + * } else { + * mySendAuthCommand( sasl.method() ); + * } + * for ( ; !sasl.dialogComplete( numResponses ) ; ++numResponses ) { + * TQByteArray challenge = myRecvChallenge(); + * mySendResponse( sasl.getResponse( challenge ) ); + * } + * return myCheckSuccess(); + * \endcode + * + * @author Michael Häckel + * @version $Id$ + */ + +class KIO_EXPORT KDESasl +{ + +public: + /** + * Construct a sasl object and initialize it with the username and password + * passed via the url. + */ + KDESasl(const KURL &aUrl); + /** + * This is a conveniece function and differs from the above function only by + * what arguments it accepts. + */ + KDESasl(const TQString &aUser, const TQString &aPass, const TQString &aProtocol); + /* + * You need to have a virtual destructor! + */ + virtual ~KDESasl(); + /** + * @returns the most secure method from the given methods and use it for + * further operations. + */ + virtual TQCString chooseMethod(const TQStrIList aMethods); + /** + * Explicitely set the SASL method used. + */ + virtual void setMethod(const TQCString &aMethod); + /** + * @return the SASL method used. + * @since 3.2 + */ + TQCString method() const; + /** + * @param numCalls number of times getResponse() has been called. + * @return whether the challenge/response dialog has completed + * + * @since 3.2 + */ + bool dialogComplete( int numCalls ) const; + /** + * @return whether the currently selected mechanism results in + * cleartext passwords being sent over the network and thus should + * be used only under TLS/SSL cover or for legacy servers. + * + * @since 3.2 + */ + bool isClearTextMethod() const; + /** + * Creates a response using the formerly chosen SASL method. + * For LOGIN authentication you have to call this function twice. KDESasl + * realizes on its own, if you are calling it for the first or for the + * second time. + * @param aChallenge is the challenge sent to create a response for + * @param aBase64 specifies, whether the authentication protocol uses base64 + * encoding. The challenge is decoded from base64 and the response is + * encoded base64 if set to true. + */ + TQCString getResponse(const TQByteArray &aChallenge=TQByteArray(), bool aBase64 = true); + /** + * Create a response as above but place it in a QByteArray + */ + TQByteArray getBinaryResponse(const TQByteArray &aChallenge=TQByteArray(), bool aBase64=true); + /** + * Returns true if the client is supposed to initiate the + * challenge-respinse dialog with an initial response (which most + * protocols can transfer alongside the authentication command as an + * optional second parameter). This method relieves the sasl user + * from knowing details about the mechanism. If true, use + * #getResponse() with a null challenge. + * + * @since 3.2 + */ + bool clientStarts() const; +protected: + /** + * PLAIN authentication as described in RFC 2595 + */ + virtual TQByteArray getPlainResponse(); + /** + * LOGIN authentication + */ + virtual TQByteArray getLoginResponse(); + /** + * CRAM-MD5 authentication as described in RFC 2195 + */ + virtual TQByteArray getCramMd5Response(const TQByteArray &aChallenge); + /** + * DIGEST-MD5 authentication as described in RFC 2831 + */ + virtual TQByteArray getDigestMd5Response(const TQByteArray &aChallenge); + +private: + TQString mProtocol, mUser, mPass; + TQCString mMethod; + bool mFirst; +}; + +#endif -- cgit v1.2.1