Version: unknown (using KDE 3.4.2, compiled sources) Compiler: gcc version 3.3.6 OS: SunOS (sun4u) release 5.8 kntlm does not work when running on Solaris running on Sparc. Looking at a packet dump, I see that the length and offset fields are in big endian format when they should be in little endian format. Firefox works, but kntlm uses the wrong byte order. Looking at the code I have traced this to kdelibs/kio/misc/kntlm/kntlm.cpp KNTLM::addBuf I think I have a fix and will attach a patch soon to this bug.
I have made some changes to kntlm.cpp which appears to fix the endian issues, however, I am still having problems, but the problem is identical to what I am seeing on Linux X86 and is not endian specific (see bug 93454 which should be reopened). I will attach my patch shortly.
Created attachment 12335 [details] Patch to fix big endian support for kntlm.cpp Here is my patch so far to fix the endian problems with kntlm.cpp.
Created attachment 12338 [details] Patch that fixes Solaris and bug 93454 This patch got connectivity working from my big-endian Solaris box to our Exchange server. This also makes bug 93454 work but is a quick hack to just work around NTLMv2 not working properly. Note that NTLMv2 does not work on a little endian system either (i586 SuSE Linux KDE 3.4.2)
Created attachment 12353 [details] Patch that fixes Solaris and bug 93454 This patch got connectivity working from my big-endian Solaris box to our Exchange server. This also makes bug 93454 work but is a quick hack to just work around NTLMv2 not working properly. Note that NTLMv2 does not work on a little endian system either (i586 SuSE Linux KDE 3.4.2)
SVN commit 454038 by gyurco: Fixes for big-endian archs. However, NTLMv2 problems needs a fix, too. BUG: 110980 M +31 -17 kntlm.cpp --- branches/KDE/3.5/kdelibs/kio/misc/kntlm/kntlm.cpp #454037:454038 @@ -34,17 +34,21 @@ QString KNTLM::getString( const QByteArray &buf, const SecBuf &secbuf, bool unicode ) { + Q_UINT32 offset; + Q_UINT16 len; + offset = KFromToLittleEndian((Q_UINT32)secbuf.offset); + len = KFromToLittleEndian(secbuf.len); //watch for buffer overflows - if ( secbuf.offset > buf.size() || - secbuf.offset + secbuf.len > buf.size() ) return QString::null; + if ( offset > buf.size() || + offset + len > buf.size() ) return QString::null; QString str; - const char *c = buf.data() + secbuf.offset; + const char *c = buf.data() + offset; if ( unicode ) { - str = UnicodeLE2QString( (QChar*) c, secbuf.len >> 1 ); + str = UnicodeLE2QString( (QChar*) c, len >> 1 ); } else { - str = QString::fromLatin1( c, secbuf.len ); + str = QString::fromLatin1( c, len ); } return str; } @@ -52,10 +56,14 @@ QByteArray KNTLM::getBuf( const QByteArray &buf, const SecBuf &secbuf ) { QByteArray ret; + Q_UINT32 offset; + Q_UINT16 len; + offset = KFromToLittleEndian((Q_UINT32)secbuf.offset); + len = KFromToLittleEndian(secbuf.len); //watch for buffer overflows - if ( secbuf.offset > buf.size() || - secbuf.offset + secbuf.len > buf.size() ) return ret; - ret.duplicate( buf.data() + secbuf.offset, buf.size() ); + if ( offset > buf.size() || + offset + len > buf.size() ) return ret; + ret.duplicate( buf.data() + offset, buf.size() ); return ret; } @@ -77,11 +85,17 @@ void KNTLM::addBuf( QByteArray &buf, SecBuf &secbuf, QByteArray &data ) { - secbuf.offset = (buf.size() + 1) & 0xfffffffe; - secbuf.len = data.size(); - secbuf.maxlen = data.size(); - buf.resize( secbuf.offset + data.size() ); - memcpy( buf.data() + secbuf.offset, data.data(), data.size() ); + Q_UINT32 offset; + Q_UINT16 len, maxlen; + offset = (buf.size() + 1) & 0xfffffffe; + len = data.size(); + maxlen = data.size(); + + secbuf.offset = KFromToLittleEndian((Q_UINT32)offset); + secbuf.len = KFromToLittleEndian(len); + secbuf.maxlen = KFromToLittleEndian(maxlen); + buf.resize( offset + len ); + memcpy( buf.data() + offset, data.data(), data.size() ); } bool KNTLM::getNegotiate( QByteArray &negotiate, const QString &domain, const QString &workstation, Q_UINT32 flags ) @@ -118,7 +132,7 @@ //challenge structure too small if ( chsize < 32 ) return false; - unicode = ch->flags & Negotiate_Unicode; + unicode = KFromToLittleEndian(ch->flags) & Negotiate_Unicode; if ( domain.isEmpty() ) dom = getString( challenge, ch->targetName, unicode ); else @@ -130,8 +144,8 @@ ((Auth*) rbuf.data())->flags = ch->flags; QByteArray targetInfo = getBuf( challenge, ch->targetInfo ); - if ( forceNTLMv2 || (!targetInfo.isEmpty() && (ch->flags & Negotiate_Target_Info)) /* may support NTLMv2 */ ) { - if ( ch->flags & Negotiate_NTLM ) { + if ( forceNTLMv2 || (!targetInfo.isEmpty() && (KFromToLittleEndian(ch->flags) & Negotiate_Target_Info)) /* may support NTLMv2 */ ) { + if ( KFromToLittleEndian(ch->flags) & Negotiate_NTLM ) { if ( targetInfo.isEmpty() ) return false; response = getNTLMv2Response( dom, user, password, targetInfo, ch->challengeData ); addBuf( rbuf, ((Auth*) rbuf.data())->ntResponse, response ); @@ -143,7 +157,7 @@ return false; } } else { //if no targetinfo structure and NTLMv2 or LMv2 not forced, try the older methods - if ( ch->flags & Negotiate_NTLM ) { + if ( KFromToLittleEndian(ch->flags) & Negotiate_NTLM ) { response = getNTLMResponse( password, ch->challengeData ); addBuf( rbuf, ((Auth*) rbuf.data())->ntResponse, response ); } else {
SVN commit 454042 by gyurco: Backport fix for #110980 (endiannes problem) CCBUG: 110980 M +31 -17 kntlm.cpp --- branches/KDE/3.4/kdelibs/kio/misc/kntlm/kntlm.cpp #454041:454042 @@ -35,16 +35,20 @@ QString KNTLM::getString( const QByteArray &buf, const SecBuf &secbuf, bool unicode ) { //watch for buffer overflows - if ( secbuf.offset > buf.size() || - secbuf.offset + secbuf.len > buf.size() ) return QString::null; + Q_UINT32 offset; + Q_UINT16 len; + offset = KFromToLittleEndian((Q_UINT32)secbuf.offset); + len = KFromToLittleEndian(secbuf.len); + if ( offset > buf.size() || + offset + len > buf.size() ) return QString::null; QString str; - const char *c = buf.data() + secbuf.offset; + const char *c = buf.data() + offset; if ( unicode ) { - str = UnicodeLE2QString( (QChar*) c, secbuf.len >> 1 ); + str = UnicodeLE2QString( (QChar*) c, len >> 1 ); } else { - str = QString::fromLatin1( c, secbuf.len ); + str = QString::fromLatin1( c, len ); } return str; } @@ -52,10 +56,14 @@ QByteArray KNTLM::getBuf( const QByteArray &buf, const SecBuf &secbuf ) { QByteArray ret; + Q_UINT32 offset; + Q_UINT16 len; + offset = KFromToLittleEndian((Q_UINT32)secbuf.offset); + len = KFromToLittleEndian(secbuf.len); //watch for buffer overflows - if ( secbuf.offset > buf.size() || - secbuf.offset + secbuf.len > buf.size() ) return ret; - ret.duplicate( buf.data() + secbuf.offset, buf.size() ); + if ( offset > buf.size() || + offset + len > buf.size() ) return ret; + ret.duplicate( buf.data() + offset, buf.size() ); return ret; } @@ -77,11 +85,17 @@ void KNTLM::addBuf( QByteArray &buf, SecBuf &secbuf, QByteArray &data ) { - secbuf.offset = (buf.size() + 1) & 0xfffffffe; - secbuf.len = data.size(); - secbuf.maxlen = data.size(); - buf.resize( secbuf.offset + data.size() ); - memcpy( buf.data() + secbuf.offset, data.data(), data.size() ); + Q_UINT32 offset; + Q_UINT16 len, maxlen; + offset = (buf.size() + 1) & 0xfffffffe; + len = data.size(); + maxlen = data.size(); + + secbuf.offset = KFromToLittleEndian((Q_UINT32)offset); + secbuf.len = KFromToLittleEndian(len); + secbuf.maxlen = KFromToLittleEndian(maxlen); + buf.resize( offset + len ); + memcpy( buf.data() + offset, data.data(), data.size() ); } bool KNTLM::getNegotiate( QByteArray &negotiate, const QString &domain, const QString &workstation, Q_UINT32 flags ) @@ -118,7 +132,7 @@ //challenge structure too small if ( chsize < 32 ) return false; - unicode = ch->flags & Negotiate_Unicode; + unicode = KFromToLittleEndian(ch->flags) & Negotiate_Unicode; if ( domain.isEmpty() ) dom = getString( challenge, ch->targetName, unicode ); else @@ -130,8 +144,8 @@ ((Auth*) rbuf.data())->flags = ch->flags; QByteArray targetInfo = getBuf( challenge, ch->targetInfo ); - if ( forceNTLMv2 || (!targetInfo.isEmpty() && (ch->flags & Negotiate_Target_Info)) /* may support NTLMv2 */ ) { - if ( ch->flags & Negotiate_NTLM ) { + if ( forceNTLMv2 || (!targetInfo.isEmpty() && (KFromToLittleEndian(ch->flags) & Negotiate_Target_Info)) /* may support NTLMv2 */ ) { + if ( KFromToLittleEndian(ch->flags) & Negotiate_NTLM ) { if ( targetInfo.isEmpty() ) return false; response = getNTLMv2Response( dom, user, password, targetInfo, ch->challengeData ); addBuf( rbuf, ((Auth*) rbuf.data())->ntResponse, response ); @@ -143,7 +157,7 @@ return false; } } else { //if no targetinfo structure and NTLMv2 or LMv2 not forced, try the older methods - if ( ch->flags & Negotiate_NTLM ) { + if ( KFromToLittleEndian(ch->flags) & Negotiate_NTLM ) { response = getNTLMResponse( password, ch->challengeData ); addBuf( rbuf, ((Auth*) rbuf.data())->ntResponse, response ); } else {